Что означает && в void * p = && abc; - PullRequest
102 голосов
/ 24 мая 2011

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

Ответы [ 2 ]

154 голосов
/ 24 мая 2011

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

void *p = &&abc недопустимо в стандартах C99 и C ++.

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

96 голосов
/ 24 мая 2011

Как это выяснить

Это адрес метки, и это особенность, характерная для 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 говорит:

ошибка: метка "a" используется, но не определена

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

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

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

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

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

Теперь метка в исходном коде - это в основном адрес. "Goto Label"; не делает ничего, кроме перехода по этому адресу (подумайте о указателе инструкций в сборке). Этот ярлык хранит этот адрес ОЗУ, и именно так вы можете узнать этот адрес.

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

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

objdump -x a.out

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...