通过C转换访问结构的第一个字段是否违反了严格的别名?

Geo*_*ing 15 c c++ strict-aliasing language-lawyer reinterpret-cast

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

struct {int x;} a;
*(int*)&a = 3
Run Code Online (Sandbox Code Playgroud)

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

bdo*_*lan 26

首先,使用C.§6.7.2.1/ 13进行投射是合法的:

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.

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

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

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

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

但是,在C++中,您经常会在C++对象的开头找到vtable和其他东西.但是,在您的具体情况下,您的结构是标准布局,因此明确允许(n3290中的§9.2/ 20,感谢Luc Danton! - C++ 03显然有类似的规则,用POD对象表示) .

  • 用于C++ 11的相关规则是一个指针,指向标准布局结构类型的对象可以是`reinterpret_cast`的指针到它的初始构件(9.2类成员[class.mem]在n3290第20段).此规则(以及涉及标准布局类型的任何内容)旨在模仿此处引用的C规则.C++ 03将有类似的东西,除了它将是POD结构,而不是标准布局结构. (7认同)