【问题标题】:C/C++ nullptr dereference [duplicate]C/C++ nullptr 取消引用 [重复]
【发布时间】:2016-12-01 14:38:51
【问题描述】:

由于取消引用 nullptr (NULL) 在 CC++ 中都是未定义的行为,我想知道如果 ptr 是 nullptr (@987654329) 表达式 &(*ptr) 是否有效@)。

如果它也是未定义的行为,链接答案中的OFFSETOF 宏如何工作?

我一直以为ptr->field(*ptr).field的简写

我认为我的问题的答案在 C 和 C++ 中是相似的。

【问题讨论】:

  • C11 标准草案 n1570:6.5.3.2 地址和间接运算符 3 一元 & 运算符产生其操作数的地址。如果操作数的类型为“type”,则结果的类型为“pointer to type”。如果操作数是一元 * 运算符的结果,则该运算符和 & 运算符都不会被计算,结果就好像两者都被省略了,除了对运算符的约束仍然适用并且结果不是左值。我>
  • 我将此标记为重复,但请务必阅读 C++ 答案下的讨论以及 this discussion,因为这在 C++ 标准中并不十分明确。
  • 我怀疑这是重复的,因为 OP 询问“如果取消引用 nullptr 是 UB,offsetof 是如何工作的”
  • @TartanLlama 由于我找不到在 c++ 中使用 &*NULL 的等效豁免,我怀疑这可能是两种语言分歧的地方之一。假设的副本只有在删除 c-tag 时才能存在。
  • 识别出的重复没有回答这个问题。

标签: c++ c null nullptr


【解决方案1】:

TL;DR &(*(char*)0) 定义明确。

C++ 标准并没有说空指针的间接寻址本身就具有 UB。当前标准草案,[expr.unary.op]

  1. 一元 * 运算符执行间接:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是一个左值,指向表达式指向的对象或函数.如果表达式的类型是“指向 T 的指针”,则结果的类型是“T”。 [剪辑]

  2. 一元 & 运算符的结果是指向其操作数的指针。操作数应为左值或限定 ID。 [剪辑]

除非将间接表达式的左值转换为右值,否则没有 UB。


C 标准更加明确。 C11 标准草案§6.5.3.2

  1. 一元 & 运算符产生其操作数的地址。如果操作数的类型为“type”,则结果的类型为“pointer to type”。 如果操作数是一元 * 运算符的结果,则该运算符和 & 运算符都不会被计算,结果就好像两者都被省略了一样,除了对运算符的约束仍然适用并且结果不是左值。类似地,如果操作数是 [] 运算符的结果,则 & 运算符和 [] 所隐含的一元 * 都不会被计算,结果就像 & 运算符被删除, [] 运算符更改为 + 运算符。否则,结果是指向其操作数指定的对象或函数的指针。

【讨论】:

    【解决方案2】:

    如果也是未定义的行为,offsetof 是如何工作的?

    更喜欢使用the standard offsetof macro。自制版本会导致编译器警告。此外:

    offsetof 需要按照上面指定的方式工作,即使一元 operator& 对于涉及的任何类型都被重载。这不能在标准 C++ 中实现,需要编译器支持。

    offsetofbuilt-in function in gcc

    【讨论】:

    • OP 指的是链接中的宏:#define OFFSETOF(type, field) ((unsigned long) &(((type *) 0)->field))
    • @Byteventurer 没有理由使用自制的offsetoff,它会导致编译器警告。使用标准的offsetof
    • 我不是在宣传宏的使用,我是在解释 OP 在提问时指的是什么......
    • 也许他是。不过,问题是关于 &(*p) 其中 p 是一个空指针,而不是关于 offsetof 本身,而他链接到的 offsetof 宏就是这样做的。在编辑之前,您错过了 IMO 问题的重点。
    • @MaximEgorushkin,我知道offsetofOFFSETOF 是不同的。然而,问题不在于使用哪一个。 OFFSETOF 只是一个简单的例子,64 支持并标记为已接受的答案。如果这样更方便,我可以再给一个example ;-)
    猜你喜欢
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 2016-07-06
    • 2018-02-01
    • 2011-03-31
    相关资源
    最近更新 更多