<stddef.h>中的'offsetof'宏是否会调用未定义的行为?

Xeo*_*Xeo 18 c++ offsetof undefined-behavior

来自MSVC实施的示例:

#define offsetof(s,m) \
    (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
//                                                   ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

可以看出,它取消引用空指针,通常会调用未定义的行为.这是规则的例外还是正在发生的事情?

Che*_*Alf 25

在语言标准说"未定义的行为"的地方,任何给定的编译器都可以定义行为.标准库中的实现代码通常依赖于此.所以有两个问题:

(1)代码UB是否与C++标准有关?

这是一个非常难的问题,因为它是一个众所周知的几乎缺陷,C++ 98/03标准从未在规范性文本中说明,一般来说,取消引用nullpointer是UB.它暗示由例外typeid,在那里它 UB.

你可以肯定地说,它是UB offsetof与非POD类型一起使用.

(2)代码UB是针对编写的编译器吗?

不,当然不.

编译器供应商的给定编译器代码可以使用该编译器的任何功能.

干杯&hth.,


AnT*_*AnT 15

"未定义行为"的概念不适用于标准库的实现,无论它是宏,函数还是其他任何东西.

一般情况下,不应将标准库视为以C++(或C)语言实现.这也适用于标准头文件.标准库应符合其外部规范,但其他所有内容都是实现细节,不受语言的所有和任何其他要求的约束.标准库应始终被认为是以某种"内部"语言实现的,这种语言可能非常类似于C++或C,但仍然不是C++或C.

换句话说,您引用的宏不会产生未定义的行为,只要它特别offsetof是标准库中定义的宏.但是如果你在代码中做了完全相同的事情(比如以相同的方式定义自己的宏),它确实会导致未定义的行为."Quod licet Jovi,non licet bovi".

  • @ 0kcats:如果问题,你的评论在上下文中是没有意义的.问题是`offsetof`是否产生UB.是否应该"利用未定义的行为"是一个完全不同的问题.答案是"不",不应该,不管有多少"专业知识".相信Boost作者"利用UB"只会意味着你误解/误解了某些东西. (2认同)
  • @ 0kcats:是的,这些论点都是真实的.举例来说,许多GCC头文件包含各种设置指令,旨在抑制警告或根据这些标准头文件中使用的特定于实现的语言特性定制其他编译器行为.这些调整在标题结束之前反转. (2认同)
  • 即使特定于实现的功能定义了语言未定义的内容,这只不过是编译器扩展.它与语言本身无关.在C +(或C)编程领域,利用这些扩展而没有和*非常好的和完整记录的原因是无能的标志. (2认同)
  • 它非常简单:用户源代码必须完全符合要求.标准库必须在功能上符合且仅在接口级别.声称这些要求在某种程度上相当甚至可比,这是荒谬的.如果他们愿意,实现可以在Fortran中自由实现标准库. (2认同)