一元 & 运算符能否产生地址 0(空指针)?

Can the unary & operator yield the address 0 (null pointer)?

C2x,6.5.3.2 地址和间接运算符,语义,3:

The unary & operator yields the address of its operand.

一个简单的问题:一元运算符 & 可以产生地址 0 (空指针)吗?

有什么例子/经验吗?

标准的相关部分是 6.3.2.3/3 (N2731),其中规定

If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

因此,&作用于任何对象的结果保证与空指针“比较不相等”。

可以。但是你必须竭尽全力让它成为可能。

有两种方法可以对实际对象执行此操作:

  1. 构造一个目标文件或链接器符号文件,您要链接的对象文件或链接器符号文件在 NULL 处导出符号。如果你 & 在那你会得到 NULL。

  2. 在某些平台上是 libc。您定义的第一个符号是 NULL。至少在一个平台上,堆管理器不得不应对这一点,因此对其进行了仔细的编码,这样编译器就永远不会观察到堆 HEAD 指针存储在 NULL 的事实。

请注意,这两个 waaaay 都来自可移植的 C,这就是重点。如果你得到 & 到 return NULL,你就会知道你做到了。这不是偶然发生的。

但是还有另一种方法:我们可以构造一个不包含真实对象的表达式,其中 & return 是 0。像这样:

&(((struct some_struct *)0)->first_member)

只见于

#define offsetof(type, member) ((size_t)&(((type *)0)->member))

不要这样做。 #include <stddef> 并让编译器定义 offsetof。此实现中存在错误。

C 2018 6.5.3.2 1 说:

The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field…

如果操作数是函数指示符,则它不能是空指针,因为 C 2018 6.3.2.3 3 说空指针“保证与指向任何对象或函数的指针比较不相等”,但是函数作为空指针的指示符将与另一个(可能不同的)空指针比较,因为 C 2018 6.5.9 6 表示两个空指针比较相等。

如果它是指定对象的左值,那么它不能是空指针,同理。 (注意6.5.3.2 1特指指定对象的左值,一般来说,左值是可能指定对象的表达式,即必须有对象类型.但是6.5.3.2 1中的约束明确告诉我们操作数必须实际指定一个对象。)

剩下 [] 或一元 * 的结果。前者是根据后者来定义的,所以我们只需要考虑一元*。 C 2018 6.5.3.2 2 说“一元 * 运算符的操作数应具有指针类型”,但并不要求它指向实际对象或函数或 non-null。 6.5.3.2 4 表示“……如果操作数指向一个函数,则结果是一个函数指示符;如果它指向一个对象,则结果是指定该对象的左值……”但没有明确说明如果操作数是空指针,结果是什么。它继续说“如果为指针分配了无效值,则一元 * 运算符的行为未定义。”那里的文本引用了注释 106,它说“......在一元 * 运算符取消引用指针的无效值中,有一个空指针,一个与指向的对象类型不恰当对齐的地址,以及生命周期结束后的对象。”

因此,C 标准没有定义一元 & 会产生空指针的行为。当然,它可能通过标准未定义的行为发生。