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

时间:2012-03-17 03:31:28

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

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

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

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

1 个答案:

答案 0 :(得分:24)

首先,在C.§6.7.2.1/ 13中投射是合法的:

  

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

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

  

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

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

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

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