简体   繁体   English

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

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

C2x, 6.5.3.2 Address and indirection operators, Semantics, 3: C2x,6.5.3.2 地址和间接运算符,语义,3:

The unary & operator yields the address of its operand.一元 & 运算符产生其操作数的地址。

A simple question: can the unary & operator yield the address 0 (null pointer)?一个简单的问题:一元运算符&可以产生地址0 (空指针)吗?

Any examples / experience?有什么例子/经验吗?

It can.它可以。 But you have to go out of your way to make it possible.但是您必须 go 才能使它成为可能。

There are two ways to do this for an actual object:对于实际的 object,有两种方法可以做到这一点:

  1. Construct an object file or linker symbol file that you are linking against that exports a symbol at NULL. If you & on that you will get NULL.构造一个 object 文件或 linker 符号文件,您要链接到该文件,并在 NULL 处导出一个符号。如果您 & 在上面,您将得到 NULL。

  2. Be libc on certain platforms.在某些平台上是 libc。 The first symbol you define is NULL. On at least one platform, the heap manager had to contend with this so it was carefully coded so the compiler would never observe the fact the heap HEAD pointer was stored at NULL.您定义的第一个符号是 NULL。至少在一个平台上,堆管理器必须应对此问题,因此对其进行了仔细编码,以便编译器永远不会观察到堆 HEAD 指针存储在 NULL 的事实。

Notice that both of these waaaay out of portable C, and that's the point.请注意,这两个都在便携式C之外,这就是重点。 If you get & to return NULL you will know you did it.如果你得到&返回 NULL 你就会知道你做到了。 It's not happening by accident.这不是偶然发生的。

However there is another way: We can construct an expression containing no real objects where & returns a 0. Like this:但是还有另一种方法:我们可以构造一个不包含真实对象的表达式,其中&返回 0。像这样:

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

Only seen in只见于

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

Don't do this.不要这样做。 #include <stddef> and let the compiler define offsetof . #include <stddef>并让编译器定义offsetof There's a bug in this implementation.这个实现中有一个错误。

C 2018 6.5.3.2 1 says: 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…一元&运算符的操作数应为 function 指示符, []或一元*运算符的结果,或指定 object 不是位域的左值……

If the operand is a function designator, it cannot be a null pointer, since C 2018 6.3.2.3 3 says a null pointer “is guaranteed to compare unequal to a pointer to any object or function,” but a function designator that were a null pointer would compare equal to another (possibly different) null pointer because C 2018 6.5.9 6 says two null pointers compare equal. If the operand is a function designator, it cannot be a null pointer, since C 2018 6.3.2.3 3 says a null pointer “is guaranteed to compare unequal to a pointer to any object or function,” but a function designator that were a null指针将与另一个(可能不同的)null 指针比较,因为 C 2018 6.5.9 6 表示两个 null 指针比较相等。

If it is an lvalue that designates an object, then it cannot be a null pointer, for the same reason.如果它是指定 object 的左值,则出于同样的原因,它不能是 null 指针。 (Note that 6.5.3.2 1 specifically refers to an lvalue that designates an object. In general, an lvalue is an expression that potentially designates an object. That is, it must have an object type. However, the constraint in 6.5.3.2 1 specifically tells us the operand must actually designate an object.) (请注意,6.5.3.2 1 特指指定一个 object 的左值。通常,左值是一个可能指定一个 object 的表达式。也就是说,它必须具有 object 类型。但是,6.5.3.2 1 中的约束特别告诉我们操作数必须实际指定一个 object。)

That leaves the result of [] or unary * .剩下[]或一元*的结果。 The former is defined in terms of the latter, so we only need to consider unary * .前者是根据后者定义的,所以我们只需要考虑一元* C 2018 6.5.3.2 2 says “The operand of the unary * operator shall have pointer type,” but it does not require it to point to an actual object or function or to be non-null. C 2018 6.5.3.2 2 说“一元*运算符的操作数应具有指针类型”,但并不要求它指向实际的 object 或 function 或非空。 6.5.3.2 4 says “… If the operand points to a function, the result is a function designator; 6.5.3.2 4 表示“……如果操作数指向 function,则结果为 function 指示符; if it points to an object, the result is an lvalue designating the object…” but does not explicitly say what the result is if the operand is a null pointer.如果它指向 object,则结果是指定对象的左值……”但没有明确说明如果操作数是 null 指针,结果是什么。 It goes on to say “ If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.”它继续说“如果为指针分配了无效值,则一元*运算符的行为未定义。” The text there refers to note 106, which says “… Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.”那里的文本引用注释 106,它说“......在一元*运算符取消引用指针的无效值中,有一个 null 指针,一个地址与指向的 object 类型不适当对齐,以及 object 之后的地址生命周期结束。”

Therefore, there is no behavior defined by the C standard in which unary & would yield a null pointer.因此,C 标准没有定义一元&会产生 null 指针的行为。 It may, of course, happen through behavior not defined by the standard.当然,它可能通过标准未定义的行为发生。

The relevant section of the standard is 6.3.2.3/3 (N2731), which states该标准的相关部分是 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.如果将 null 指针常量转换为指针类型,则生成的指针(称为 null 指针)保证与指向任何 object 或 function 的指针比较不相等。

Consequently, the result of & acting on any object is guaranteed to "compare unequal" with a null pointer.因此, &作用于任何 object 的结果保证与 null 指针“比较不相等”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM