Я наткнулся на кусок кода void *p = &&abc;
. Какое &&
здесь значение? Я знаю о ссылках на rvalue, но думаю, что &&
в этом контексте они используются по-другому. Что &&
указывает в void *p = &&abc;
?
Я наткнулся на кусок кода void *p = &&abc;
. Какое &&
здесь значение? Я знаю о ссылках на rvalue, но думаю, что &&
в этом контексте они используются по-другому. Что &&
указывает в void *p = &&abc;
?
Ответы:
&&
является расширением gcc для получения адреса метки, определенной в текущей функции.
void *p = &&abc
недопустимо в стандартных C99 и C ++.
Это компилируется с g ++.
void*
.
__forceinline
? __declspec(naked)
? Один из моих любимых MSVCisms:, template<typename T> class X { friend T; }
который является недопустимым C ++ 03.
Это адрес метки, и это особенность 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», в Linux есть «Загрузчик ELF» или, возможно, даже другие, если они скомпилированы в kernel), он выполняет «виртуализацию» этой программы, превращая ее в процесс.
Этот процесс считает, что он единственный в ОЗУ и имеет доступ ко всей ОЗУ (то есть 0x00000000-0xFFFFFFFF на 32-битной машине).
(приведенное выше - это лишь краткий обзор того, что происходит, вам действительно нужно изучить сборку, чтобы полностью понять это, так что терпите меня)
Теперь метка в исходном коде - это, по сути, адрес. "goto label;" ничего не делает, кроме перехода к этому адресу (подумайте об указателе инструкции в сборке). На этой этикетке хранится этот адрес ОЗУ, и именно так вы можете узнать этот адрес.
Изучив ASM, вы поймете, что этот адрес указывает на инструкцию в .text
разделе исполняемого файла. В.text
разделе хранится исполняемый (двоичный) код вашей программы.
Вы можете проверить это с помощью:
objdump -x a.out
Как описано в GCC , вы можете использовать это для инициализации таблицы переходов. Некоторые генераторы сканеров, такие как re2c (см. -g
Параметр), используют это для создания более компактных сканеров. Может быть, есть даже генератор парсеров, использующий ту же технику.