Я натрапив на фрагмент коду 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 Loader", у Linux є "ELF loader" або, можливо, навіть інші), якщо вони складені в ядро), воно робить "віртуалізацію" цієї програми, перетворюючи її на процес.
Цей процес вважає, що він є єдиним в оперативній пам'яті, і він має доступ до всієї ОЗУ (тобто 0x00000000-0xFFFFFFFF на 32-бітній машині).
(вище - лише короткий перегляд того, що відбувається, вам дійсно потрібно навчитися збірці, щоб зрозуміти це повністю, тому поводьтеся зі мною)
Тепер мітка у вихідному коді - це в основному адреса. "goto label;" не робить нічого іншого, як стрибок на цю адресу (подумайте про вказівник інструкцій щодо складання). Ця мітка зберігає цю адресу оперативної пам’яті, і саме так ви можете дізнатися її.
Після того як ви дізналися ASM, ви зрозумієте, що ця адреса вказує на інструкцію в .text
розділі виконуваного файлу. .text
Розділ є той , який має код , який ви програма (двійковий) для виконання.
Ви можете перевірити це за допомогою:
objdump -x a.out
Як описано в GCC , ви можете використовувати це для ініціалізації таблиці стрибків. Деякі генератори сканерів, такі як re2c (див. -g
Параметр), використовують для створення більш компактних сканерів. Можливо, є навіть генератор парсера, який використовує ту саму техніку.