Как void * a = & законно?
Рассмотрим следующий код С++:
void* a = &a;
Почему компилятор не жалуется на использование необъявленного идентификатора?
Кроме того, что компилятор считает переменной a
? Является ли это указателем на объект void или является указателем на указатель void*
?
Ответы
Ответ 1
Объем объявления переменных на С++ может быть довольно неожиданным:
void* a = &a;
^~~~~~~~~~~~~~~~~
a declared as `void*` from here on
Следовательно, &a
есть void**
, но поскольку любой тип указателя неявно конвертируется в void*
...
Ответ 2
Это эквивалентно
void* a;
a = &a;
Следовательно, a
объявлен. Итак, a
получает адрес a
, записанный в a
. Таким образом, это указатель на указатель void. (Вы еще не определили какие-либо объекты.)
Ответ 3
В void* a
, a
объявляется как указатель не на тип void
, а на "любой" тип (особый случай). Адрес (позиция в памяти) присваивается a
, как и любая другая объявляемая переменная, конечно.
После этого выражение &a
оценивается для инициализации переменной (также a
, но это не имеет значения) только что объявлено. Тип &a
- это "указатель на указатель на любой тип", который является частным случаем "указателя на любой тип", полностью совместимого с типом a
. Ergo, нет сообщений компилятора.
Следствие: не используйте void*
, если вам нужна сильная проверка типов. Все может быть преобразовано в него. Как раз наоборот в обратном направлении, кроме самого void*
(было бы лишним исключением, что тип был несовместим с самим собой).
Кроме того, AFAIR это действительно происходит от C.
Ответ 4
Хорошо, если указатель void
указывает на любой адрес. Проблема в том, когда вы разыгрываете ее. Вы должны указать его на тот тип, который вы ожидаете от этого указателя.