字符*转换和混叠规则

char* conversion and aliasing rules

本文关键字:规则 转换 字符      更新时间:2023-10-16

根据严格的混叠规则:

struct B { virtual ~B() {} };
struct D : public B { };
D d;
char *c = reinterpret_cast<char*>(&d);

一个char*对任何不同类型的对象都是有效的。但现在的问题是,它会指向&d的相同地址吗?c++标准如何保证它会返回相同的地址?

c&d确实具有相同的值,如果将c重新解释为D*,则可以得到一个可以解引用的有效指针。此外,您可以将c视为不透明数组char[sizeof(D)](指向其第一个元素的指针)——这确实是将指针转换为char指针的主要目的:为了允许(反)序列化(例如ofile.write(c, sizeof(D));),尽管您通常应该只对基本类型(及其数组)这样做,因为复合类型的二进制布局通常不是以可移植的方式指定的。

正如@Oli正确指出并希望我强调的那样,您真的不应该将复合类型作为一个整体序列化。结果几乎永远不会是可反序列化的,因为多态类的实现和数据字段之间的填充没有指定,也不能被您访问。

注意,reinterpret_cast<char*>(static_cast<B*>(&d))也可以被当作一个不透明的数组char[sizeof(B)]

2003年c++标准第5.2.10节,第7点说:

指向对象的指针可以显式地转换为指向对象的指针不同类型的对象。类型的右值的转换将"指向T1的指针"转换为"指向T2的指针"类型(其中T1和T2分别为)对象类型,其中T2的对齐要求没有比T1)和更严格,返回到其原始类型初始指针值,指针转换的结果为未指明的。

如果"相同地址"指的是"原始指针值",那么这一项表示"是"。"

意图很明确(不需要争论):

reinterpret_cast永远不会改变地址的值,除非目标类型不能表示所有的地址值(比如一个小整数类型,在具有内在对齐的指针类型上)。只能表示偶数地址的指针,或者指向对象的指针和指向函数的指针不能混合使用……

标准的措辞没有捕捉到这一点,但这并不意味着这里存在真正的实际问题。

char *c = reinterpret_cast<char*>(&d);

c总是指向d的第一个字节。