通常认为offsetof()可以应用于联合(您甚至可以在SO的几个问题中找到这样的用法),但是,从C90到现在的所有C规范似乎都只说offsetof()宏支持结构体。我现在正在看"现代"Jens Gustedt的书,表4.3指定了"结构"。作为offsetof()的第一个参数的类型。
所以,……offsetof()是否正式支持联合?
这实际上是C规范中的一个缺陷,直到C2x。这是在C11规范DR 496的缺陷报告中提出的,在C2x中得到了解决。
来自C11规范§7.19第3段,offsetof
的定义:
offsetof(type, member-designator)
扩展为类型为
size_t
的整型常量表达式,其值为以字节为单位的偏移量,从结构的开头(由成员指示符指定)到结构成员(由类型指定)。类型和成员指示符应使给定
static type t;
则表达式
&(t.member-designator)
求值为地址常数。(如果指定的成员是位域,则行为未定义)
类型参数被描述为一个"结构成员",但是表达式&(t.member-designator)
也定义为联合类型(第6.7.2.1节第16段)。这给编译器作者带来了歧义,所以大多数人选择允许联合使用offsetof
。
在C2x规范中,它被改写为(粗体强调):
offsetof(type, member-designator)
扩展为类型为
size_t
的整型常量表达式,其值为子对象的偏移量(以字节为单位)。(由成员指示符指定),从开始的类型为类型为的任何对象. 类型和成员指示符应使给定
static type t;
则表达式
&(t.member-designator)
的计算结果为地址常数。如果指定的类型定义了新类型或者如果指定的成员是位域,则行为未定义。
变化如下:
- "结构member"→"subobject">
- "结构开头"→类型的任何对象的开头">
- 在新类型声明中使用
offsetof
是未定义的行为
回答"offsetof
是否适用于union"的问题:
- 在C2x中,是
- 在旧版本中,也可能是,因为许多编译器支持它