这段代码是否违反了严格的别名?
struct {int x;} a;
*(int*)&a = 3
更抽象地说,只要原始读/写操作类型正确,在不同类型之间进行强制转换是否合法?
这段代码是否违反了严格的别名?
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 对象表示) .