Как это выяснить
Это адрес метки, и это особенность, характерная для 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
), используют это для создания более компактных сканеров. Может быть, есть даже генератор парсеров , использующий ту же технику.