Подтвердить что ты не робот

Что означает && в void * p = && abc;

Я наткнулся на фрагмент кода void *p = &&abc;. Каково значение && здесь? Я знаю о ссылках rvalue, но я думаю, что &&, используемые в этом контексте, различны. Что означает && в void *p = &&abc;?

4b9b3361

Ответ 1

&& - расширение gcc, чтобы получить адрес метки, определенный в текущей функции.

void *p = &&abc является незаконным в стандартных C99 и С++.

Это компилируется с g++.

Ответ 2

Как найти

Это адрес метки, и это функция, характерная для GCC.

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

Вы могли бы подумать о себе, протестировав:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

В этом случае GCC говорит:

error: label 'a used, но не определен

Под капотом - сборка

Вам нужно знать ассемблера, чтобы это понять, но я попытаюсь объяснить вам, что означает адрес метки.

После того, как ОС загрузит файл .exe с диска, компонент операционной системы, называемый "загрузчиком" (в Windows есть "загрузчик PE", linux имеет "загрузчик ELF" или, возможно, даже другие, если они скомпилированный в ядре), он выполняет "виртуализацию" этой программы, превращая ее в процесс.

Этот процесс считает, что он единственный в ОЗУ и имеет доступ ко всей ОЗУ (то есть 0x00000000-0xFFFFFFFF на 32-разрядной машине).

(вышесказанное представляет собой лишь краткое описание того, что происходит, вам действительно нужно научиться сборке, чтобы полностью ее понять, так что несите меня)

Теперь метка в исходном коде является в основном адресом. "goto label"; не делает ничего, кроме перехода на этот адрес (подумайте о указателе инструкции в сборке). Этот ярлык хранит этот адрес RAM и что вы можете узнать этот адрес.

После того, как вы узнали ASM, вы поймете, что этот адрес указывает на инструкцию в разделе .text исполняемого файла. Раздел .text - это тот, который содержит исполняемый программный (двоичный) код.

Вы можете проверить это с помощью

objdump -x a.out

Практический пример

Как описано в GCC, вы можете использовать это для инициализации таблицы перехода. Некоторые генераторы сканеров такие как re2c (см. Параметр -g), используют это для создания более компактных сканеров, Может быть, даже генератор синтаксического анализа использует ту же технику.