C offsetof() 宏可以应用于联合吗?

ces*_*sss 5 c language-lawyer

人们通常认为 offsetof() 可以应用于联合(您甚至可以在 SO 的几个问题中找到这种用法),但是,似乎从 C90 到现在的所有 C 规范都只说 offsetof() 宏支持结构。我现在正在看 Jens Gustedt 的《Modern C》一书,表 4.3 指定“struct”作为 offsetof() 第一个参数的类型。

那么,... offsetof() 是否正式支持联合?

eso*_*ote 5

这实际上是 C 规范中的一个缺陷,直到 C2x。这是在 C11 规范DR 496的缺陷报告中提出的,已在 C2x 中解决。

\n

C11 规范部分 \xc2\xa77.19 第 3 段中,定义offsetof

\n
\n

offsetof(type, member-designator)

\n

它扩展为具有 type 的整数常量表达式size_t,其值是从其结构开头(由 type 指定)到结构成员(由member-designator指定)的偏移量(以字节为单位)。类型和成员指示符应给定

\n

static type t;

\n

然后表达式的&(t.member-designator)计算结果为地址常量。(如果指定的成员是位字段,则行为未定义。)

\n
\n

类型参数被描述为“结构成员”,但表达式对于联合类型也是明确定义的(\xc2\xa76.7.2.1 第 16 段)&(t.member-designator)这给编译器作者带来了歧义,因此大多数人选择允许offsetof联合。

\n

在 C2x 规范中,这被重新措辞(粗体强调我的):

\n
\n

offsetof(type, member-designator)

\n

它扩展为具有 type 的整数常量表达式size_t,其值是从任何类型为 type 的对象的开头到子对象(由member-designator指定)的偏移量(以字节为单位) 。类型和成员指示符应给定

\n

static type t;

\n

然后表达式的&(t.member-designator)计算结果为地址常量。如果指定的类型定义了新类型或者指定的成员是位字段,则行为未定义。

\n
\n

变化是:

\n
    \n
  • “结构成员”->“子对象”
  • \n
  • “其结构的开始”->“任何类型为type的对象的开始”
  • \n
  • offsetof在新类型声明上使用是未定义的行为
  • \n
\n
\n

offsetof回答“可以适用于工会”的问题:

\n
    \n
  • 在 C2x 中,是的
  • \n
  • 在旧版本中,考虑到许多编译器都支持它,也可能是的
  • \n
\n