Розглянемо такий код С ++:
void* a = &a;
Чому компілятор не скаржиться на використання незадекларованого ідентифікатора?
Крім того, яким вважає компілятор змінну a? Це вказівник на порожній об’єкт чи це вказівник на void*вказівник?
Розглянемо такий код С ++:
void* a = &a;
Чому компілятор не скаржиться на використання незадекларованого ідентифікатора?
Крім того, яким вважає компілятор змінну a? Це вказівник на порожній об’єкт чи це вказівник на void*вказівник?
Відповіді:
Сфера оголошення змінних у C ++ може бути досить дивною:
void* a = &a;
^~~~~~~~~~~~~~~~~
a declared as `void*` from here on
Отже, &aє, void**але оскільки будь-який тип покажчика неявно конвертується в void*...
a = &userfulObject?
void *a = a;це буде UB, якщо це буде оголошено локально, інакше це чудово в області простору імен.
Це еквівалентно
void* a;
a = &a;
Тому aбуло оголошено. Так aотримує адресу, aнаписану в a. Отже, це вказівник на порожній вказівник. (Ви ще не визначили жодного об’єкта.)
aсам є об'єктом. (Не всі об'єкти мають визначені користувачем типи в C ++)
In void* a, aоголошується як покажчик не на voidтип, а на "будь-який" тип (особливий випадок). Адреса (позиція в пам'яті) присвоюється a, як і будь-якій іншій змінній, що оголошується, звичайно.
Після цього вираз &aобчислюється для ініціалізації змінної (також a, але це не актуально), щойно оголошеної. Тип &a"вказівник на вказівник на будь-який тип", що є особливим випадком "вказівник на будь-який тип", повністю сумісний з типом a. Ерго, повідомлення компілятора відсутнє.
Висновок: не використовуйте, void*якщо ви хочете сильну перевірку типу. Будь-що можна перетворити на це. Якраз протилежне у зворотному напрямку, за винятком void*самого себе (було б непотрібним винятком, що тип був несумісний із самим собою).
Крім того, AFAIR це справді походить від C.