通过C转换访问结构的第一个字段是否违反了严格的别名?
此代码是否违反严格别名?
struct {int x;} a; *(int*)&a = 3
更抽象的是,只要原始读/写操作类型正确,在不同类型之间进行转换是否合法?
首先,使用C.§6.7.2.1/ 13进行投射是合法的:
在结构对象中,非位字段成员和位字所在的单元具有按声明顺序增加的地址。 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 结构对象中可能存在未命名的填充,但不是在其开头。
别名规则如下(§6.5/ 7):
对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,
- 与对象的有效类型对应的有符号或无符号类型的类型,
- 与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
- 在其成员中包含上述类型之一的聚合或联合类型(包括递归地,子聚合或包含联合的成员),或者
- 一个字符类型。
在这里,您将通过“与对象的有效类型兼容的类型”和“包含其成员中的上述类型之一的聚合或联合类型”的指针来访问它,因此别名也没有问题。 因此,在C中,通过将指向结构的指针强制转换为相关成员的类型来访问结构的第一个成员确实是完全合法的。
但是,在C ++中,您经常会在C ++对象的开头找到vtable和其他东西。 但是,在您的特定情况下,您的结构是标准布局,因此明确允许(n3290中的§9.2/ 20,感谢Luc Danton! – C ++ 03显然有类似的规则,用POD对象表示) 。