Я наткнулся на кусок кода void *p = &&abc;. Какое &&здесь значение? Я знаю о ссылках на rvalue, но думаю, что &&в этом контексте они используются по-другому. Что &&указывает в void *p = &&abc;?
А теперь представьте, насколько лучше были бы программисты, если бы в gcc по умолчанию была -pedantic. Тогда люди будут изучать C вместо нерелевантной информации о gnus.
Lundin
4
Что за взлом. Если они изобретают новый синтаксис для указателей меток, они должны также изобрести новый тип для него вместо использования void*.
Марк Рэнсом
1
@Prasoon Saurav: Тот, кто проголосовал против, вероятно, не одобряет эту функцию и отказывается от нее.
Чак
@Lundin: То же самое можно сказать и о большинстве компиляторов. __forceinline? __declspec(naked)? Один из моих любимых MSVCisms:, template<typename T> class X { friend T; }который является недопустимым C ++ 03.
int main(void){void* startp;
s:
startp =&&s;
printf("the assignment above starts at address %p\n", startp);return0;}
Вы могли понять это сами, протестировав:
int main(void){void* startp;int a;
startp =&&a;
printf("startp=%p\n", startp);return0;}
В этом случае GCC говорит:
ошибка: метка 'a' используется, но не определена
Под капотом - сборка
Вам нужно знать ассемблер, чтобы понять это, но я попытаюсь объяснить вам, что означает адрес метки.
После того, как ОС загружает файл .exe с диска, компонент операционной системы называется «загрузчик» (в Windows есть «Загрузчик PE», в Linux есть «Загрузчик ELF» или, возможно, даже другие, если они скомпилированы в kernel), он выполняет «виртуализацию» этой программы, превращая ее в процесс.
Этот процесс считает, что он единственный в ОЗУ и имеет доступ ко всей ОЗУ (то есть 0x00000000-0xFFFFFFFF на 32-битной машине).
(приведенное выше - это лишь краткий обзор того, что происходит, вам действительно нужно изучить сборку, чтобы полностью понять это, так что терпите меня)
Теперь метка в исходном коде - это, по сути, адрес. "goto label;" ничего не делает, кроме перехода к этому адресу (подумайте об указателе инструкции в сборке). На этой этикетке хранится этот адрес ОЗУ, и именно так вы можете узнать этот адрес.
Изучив ASM, вы поймете, что этот адрес указывает на инструкцию в .textразделе исполняемого файла. В.text разделе хранится исполняемый (двоичный) код вашей программы.
Вы можете проверить это с помощью:
objdump -x a.out
Практический пример
Как описано в GCC , вы можете использовать это для инициализации таблицы переходов. Некоторые генераторы сканеров, такие как re2c (см. -gПараметр), используют это для создания более компактных сканеров. Может быть, есть даже генератор парсеров, использующий ту же технику.
Ответы:
&&
является расширением gcc для получения адреса метки, определенной в текущей функции.void *p = &&abc
недопустимо в стандартных C99 и C ++.Это компилируется с g ++.
источник
void*
.__forceinline
?__declspec(naked)
? Один из моих любимых MSVCisms:,template<typename T> class X { friend T; }
который является недопустимым C ++ 03.Как это узнать
Это адрес метки, и это особенность GCC .
Вы могли понять это сами, протестировав:
В этом случае GCC говорит:
Под капотом - сборка
Вам нужно знать ассемблер, чтобы понять это, но я попытаюсь объяснить вам, что означает адрес метки.
После того, как ОС загружает файл .exe с диска, компонент операционной системы называется «загрузчик» (в Windows есть «Загрузчик PE», в Linux есть «Загрузчик ELF» или, возможно, даже другие, если они скомпилированы в kernel), он выполняет «виртуализацию» этой программы, превращая ее в процесс.
Этот процесс считает, что он единственный в ОЗУ и имеет доступ ко всей ОЗУ (то есть 0x00000000-0xFFFFFFFF на 32-битной машине).
(приведенное выше - это лишь краткий обзор того, что происходит, вам действительно нужно изучить сборку, чтобы полностью понять это, так что терпите меня)
Теперь метка в исходном коде - это, по сути, адрес. "goto label;" ничего не делает, кроме перехода к этому адресу (подумайте об указателе инструкции в сборке). На этой этикетке хранится этот адрес ОЗУ, и именно так вы можете узнать этот адрес.
Изучив ASM, вы поймете, что этот адрес указывает на инструкцию в
.text
разделе исполняемого файла. В.text
разделе хранится исполняемый (двоичный) код вашей программы.Вы можете проверить это с помощью:
Практический пример
Как описано в GCC , вы можете использовать это для инициализации таблицы переходов. Некоторые генераторы сканеров, такие как re2c (см.
-g
Параметр), используют это для создания более компактных сканеров. Может быть, есть даже генератор парсеров, использующий ту же технику.источник