char *转换和别名规则

时间:2011-12-18 22:02:19

标签: c++ pointers reinterpret-cast strict-aliasing

根据严格的别名规则:

struct B { virtual ~B() {} };
struct D : public B { };

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

char*对任何不同类型的对象都有效。但现在的问题是,它是否会指向&amp; d的相同地址? C ++标准保证它将返回相同的地址是什么?

3 个答案:

答案 0 :(得分:6)

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

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

请注意,reinterpret_cast<char*>(static_cast<B*>(&d))可以通过类似的推理视为不透明数组char[sizeof(B)]

答案 1 :(得分:2)

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

  

指向对象的指针可以显式转换为指向的指针   不同类型的对象。除了转换类型的右值   “指向T1的指针”到“指向T2的指针”(其中T1和T2为   对象类型以及T2的对齐要求为否   比T1更严格,回到原来的类型产生了   原始指针值,这种指针转换的结果是   未指定的。

如果“同一地址”表示“原始指针值”,则此条目显示“是”。

答案 2 :(得分:0)

意图很明确(而不是需要辩论的事情):

reinterpret_cast永远不会更改地址的值,除非目标类型无法表示所有地址值(如小型整数类型,具有内部对齐的指针类型:f.ex 。一个只能表示偶数地址的指针,或者指向对象的指针和指向函数的指针不能混合......)。

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

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

c将始终指向d的第一个字节。