Рассмотрим следующий код C ++:
void* a = &a;
Почему компилятор не жалуется на использование необъявленного идентификатора?
Кроме того, что компилятор считает переменной a? Это указатель на объект void или указатель на void*указатель?
Рассмотрим следующий код C ++:
void* a = &a;
Почему компилятор не жалуется на использование необъявленного идентификатора?
Кроме того, что компилятор считает переменной a? Это указатель на объект void или указатель на 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. Так что это указатель на указатель void. (Вы еще не определили никаких объектов.)
aсам по себе является объектом. (Не все объекты имеют определяемые пользователем типы в C ++)
В void* a, aобъявлен как указатель не к voidтипу , а к «любой» типа (частный случай). Адрес (позиция в памяти) присваивается a, как и любой другой объявленной переменной, конечно.
После этого выражение &aвычисляется для инициализации только что объявленной переменной (также a, но это не имеет значения). Типом &aявляется «указатель на указатель на любой тип», который является частным случаем «указателя на любой тип», полностью совместимого с типом a. Ergo, нет сообщения компилятора.
Следствие: не используйте, void*если хотите строгую проверку типов. В него можно преобразовать все что угодно . Как раз наоборот, в обратном направлении, кроме void*самого себя (было бы ненужным исключением, если бы тип был несовместим сам с собой).
Кроме того, AFAIR это действительно исходит от C.