Як недійсний * a = & юридичний?


88

Розглянемо такий код С ++:

void* a = &a;

Чому компілятор не скаржиться на використання незадекларованого ідентифікатора?

Крім того, яким вважає компілятор змінну a? Це вказівник на порожній об’єкт чи це вказівник на void*вказівник?




15
Слід згадати, чому ви хочете це зробити - отримати вказівник на верх стека (з якого ви можете возитися з усіма різними речами).
OrangeDog

Відповіді:


95

Сфера оголошення змінних у C ++ може бути досить дивною:

void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

Отже, &aє, void**але оскільки будь-який тип покажчика неявно конвертується в void*...


Як мені призначити для цього корисний об’єкт?
user2681063

22
@ користувач2681063 a = &userfulObject?
Нікос К.

4
@MarkGarcia: Зверніть увагу, що void *a = a;це буде UB, якщо це буде оголошено локально, інакше це чудово в області простору імен.
Nawaz

1
@TheodorosChatzigiannakis: Я б повірив, що так, так.
Matthieu M.

1
Тут буде дуже приємне цитування специфікації.
Бенджамін Груенбаум,

30

Це еквівалентно

void* a;
a = &a;

Тому aбуло оголошено. Так aотримує адресу, aнаписану в a. Отже, це вказівник на порожній вказівник. (Ви ще не визначили жодного об’єкта.)


9
Технічно ви визначили один об’єкт. aсам є об'єктом. (Не всі об'єкти мають визначені користувачем типи в C ++)
MSalters

1
@MSalters, про що це "об'єкт", про який ти говориш? : D
Гусдор

3
@Gusdor Ми можемо лише припустити, що лежить поза пустотою горизонту подій.
Коул Джонсон,

Їх називають по-різному, однак "ефект" у цьому випадку однаковий
Стасік

Вони загалом не рівнозначні, але в цьому випадку вони є.
Гонки легкості на орбіті

7

In void* a, aоголошується як покажчик не на voidтип, а на "будь-який" тип (особливий випадок). Адреса (позиція в пам'яті) присвоюється a, як і будь-якій іншій змінній, що оголошується, звичайно.

Після цього вираз &aобчислюється для ініціалізації змінної (також a, але це не актуально), щойно оголошеної. Тип &a"вказівник на вказівник на будь-який тип", що є особливим випадком "вказівник на будь-який тип", повністю сумісний з типом a. Ерго, повідомлення компілятора відсутнє.

Висновок: не використовуйте, void*якщо ви хочете сильну перевірку типу. Будь-що можна перетворити на це. Якраз протилежне у зворотному напрямку, за винятком void*самого себе (було б непотрібним винятком, що тип був несумісний із самим собою).

Крім того, AFAIR це справді походить від C.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.