void *a = &a 合法吗?

88

考虑下面的C++代码:

void* a = &a;

编译器为什么不会因为使用未声明的标识符而抱怨呢?

此外,编译器认为变量a是什么?它是指向void对象的指针还是指向void*指针的指针?


6
声明点(Point of Declaration)。 - Grijesh Chauhan
4
C++ 中的声明点指的是在程序中声明一个变量时,其名字和类型已经确定,但是其值还未被初始化的那个点。在此之后,该变量将会分配内存并成为可用的对象。需要注意的是,在 C++11 之前,声明点通常被称为定义点,但是这种区分方式已经过时。 - masoud
15
应该提到为什么要这样做 - 以获取指向堆栈顶部的指针(从中可以调整各种事情)。 - OrangeDog
3个回答

95
在C++中,变量的声明范围可能会让人感到惊讶:
void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

因此,&avoid** 类型,但由于任何指针类型都可以隐式转换为 void* 类型...

22
@a = &userfulObject? - Nikos C.
4
请注意,如果在本地声明,则 void *a = a; 将是未定义行为,否则在命名空间范围内使用则没问题。 - Nawaz
1
@TheodorosChatzigiannakis:我相信是这样的,是的。 - Matthieu M.
好的,现在问题变成了:为什么允许这样做?我理解作用域,但我不明白为什么你想要做 int a; void *a = &a - Cole Tobin
1
这里最好能有一个规格引用。 - Benjamin Gruenbaum
显示剩余5条评论

30

它相当于

void* a;
a = &a;
因此,a 已经声明。所以 a 获取了写在 a 中的地址。因此它是一个指向空指针的指针。(您尚未定义任何对象。)

9
从技术上讲,你确实定义了一个对象。a本身就是一个对象。(在C++中,并不是所有的对象都有用户定义的类型。) - MSalters
1
@MSalters,你所说的“object”是什么? :D - Gusdor
3
我们只能假设事件视界之外存在什么。 - Cole Tobin
它们被称为不同的名称,但在这种情况下,“效果”是相同的。 - Stasik
一般情况下它们并不等价,但在这种情况下它们是等价的。 - Lightness Races in Orbit

7
在`void* a`中,`a`被声明为指向"任何"类型(特殊情况)的指针,而不是`void`类型的指针。当然,与任何其他被声明的变量一样,一个地址(内存中的位置)被分配给`a`。
在此之后,表达式`&a`被评估以初始化刚刚声明的变量(也是`a`,但这并不重要)。`&a`的类型是“指向任何类型的指针的指针”,这是“指向任何类型的指针”的特殊情况,完全兼容`a`的类型。因此,没有编译器消息。
推论:如果您想进行强类型检查,请不要使用`void*`。任何东西都可以转换为它。相反,在相反的方向上完全相反,除了`void*`本身(将类型与其自身不兼容是不必要的例外)。
另外,据我所知,这确实来自C。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接