【问题标题】:Can the C offsetof() macro be applied to unions?C offsetof() 宏可以应用于联合吗?
【发布时间】:2021-10-29 16:03:12
【问题描述】:

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

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

【问题讨论】:

  • 重点是什么?无论如何,union 中的每个字段都位于偏移量 0
  • @EugeneSh。没有。联合可以包含匿名结构。此结构中成员的偏移量可以不为零
  • @tstanisl 对...不管怎样,标准将“结构”作为参数进行讨论,但是宏的“典型”实现可以很好地与联合体一起使用。
  • A union 只是一个大到足以容纳任何指定类型并保存最后分配的类型的存储。 offsetof() 在那里毫无意义。
  • @tstanisl 如果将其应用于嵌套结构,那么重要的是结构,而不是父联合。他们不在一个级别

标签: c language-lawyer


【解决方案1】:

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

来自C11 spec §7.19 第 3 段,offsetof 的定义:

offsetof(type, member-designator)

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

static type t;

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

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

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

offsetof(type, member-designator)

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

static type t;

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

变化如下:

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

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

  • 在 C2x 中,是的
  • 在旧版本中,可能也是如此,因为许多编译器都支持它

【讨论】:

  • 很好的答案和引用。至少编译器编写者现在可以确定所有歧义已消除。虽然现在明确支持任何带有子对象的类型,但对于union,它最终会成为“一路乌龟”。零就是零就是零。所以在申请工会时似乎有点“哼哼”。
猜你喜欢
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多