【问题标题】:Does accessing the first field of a struct via a C cast violate strict aliasing?通过 C 强制转换访问结构的第一个字段是否违反了严格的别名?
【发布时间】:2012-04-02 13:42:39
【问题描述】:

此代码是否违反严格别名?

struct {int x;} a;
*(int*)&a = 3

更抽象地说,只要原始读/写操作类型正确,在不同类型之间进行强制转换是否合法?

【问题讨论】:

  • V-tables 可能排在第一位,所以这是 UB 领域。
  • @ildjarn,C 中不存在 vtables
  • @bdonlan :这也被标记为c++。 ;-]
  • 你为什么需要这样的东西?只需&a.x
  • 编译器优化后的代码才会这样。我知道a.x 语法。 :)

标签: c++ c language-lawyer reinterpret-cast strict-aliasing


【解决方案1】:

首先,在 C 中强制转换是合法的。§6.7.2.1/13:

在结构对象中,非位域成员和单元 哪些位域的地址按顺序增加 他们被宣布。指向结构对象的指针,适当地 转换后,指向其初始成员(或者如果该成员是 位域,然后到它所在的单元),反之亦然。 结构对象内可能有未命名的填充,但在其 开始。

别名规则如下(§6.5/7):

一个对象的存储值只能由具有以下之一的左值表达式访问 以下类型:

  • 与对象的有效类型兼容的类型,
  • 与对象的有效类型兼容的类型的限定版本,
  • 对应于有效类型的有符号或无符号类型 对象,
  • 一种类型,它是有符号或无符号类型,对应于 对象的有效类型,
  • 一种聚合或联合类型,其中包括上述类型之一 成员(递归地包括子聚合或包含联合的成员),或
  • 一种字符类型。

在这里,您将通过“与对象的有效类型兼容的类型”和“在其成员中包含上述类型之一的聚合或联合类型”的指针访问它,因此别名也没有问题。所以在 C 中,通过将指向结构的指针转换为相关成员的类型来访问结构的第一个成员确实是完全合法的。

然而,在 C++ 中,您经常会在 C++ 对象的开头找到 vtable 和其他内容。但是,在您的特定情况下,您的结构是标准布局,因此这是明确允许的(n3290 中的第 9.2/20 节,感谢 Luc Danton!-C++03 显然有类似的规则,以 POD 对象表示) .

【讨论】:

  • C++ 绝对不会掩盖 vtable 的存在,但我只在没有这种奇怪的情况下应用它。
  • @Geoffrey :“没有这种奇怪的案例”。又名微不足道的可复制类型?又是您应该在问题中提到的内容?
  • 好吧,问题提到结构有一个单一的 int 字段,这意味着没有 vtable。标题已经很冗长了。
  • C++11 的相关规则是指向标准布局结构类型对象的指针可以是reinterpret_cast 指向其初始成员的指针(9.2 类成员 [class.mem] n3290 中的第 20 段)。此规则(以及任何涉及标准布局类型的内容)旨在模仿此处引用的 C 规则。 C++03 会有类似的东西,只是它是 POD 结构,而不是标准布局结构。
  • 你必须证明两件不同的事情:(1)定义了强制转换,并返回一个有效的指针(2)可以取消引用指针,可以访问左值
猜你喜欢
  • 2018-09-03
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多