字符*转换和混叠规则
char* conversion and aliasing rules
根据严格的混叠规则:
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
的第一个字节。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 为什么此指针值不能转换为整数的规则是什么?
- 强制转换为不相关的引用类型是否违反严格的别名规则?
- 初始化中的模板转换运算符类型推导规则是什么?
- 隐式数值类型转换的规则
- 右值到左值的转换和"named-refs-are-lvalues"规则
- 从char数组中强制转换*时,严格的别名规则是什么
- 使用指针转换来存储/转换值:我打破了严格的别名规则吗
- 将Javascript正则表达式模式转换为C++std::regex的规则
- C++整数转换规则
- MISRA C++ 2008 违反规则 5-2-7:不得直接或间接将指针类型的对象转换为不相关的指针类型
- 在指针类型之间转换的规则,其中cv限定符是唯一的区别
- 取消引用类型punned指针将打破严格的混叠规则:将字节数组转换为数字
- 将char[]强制转换为usingned int给出:取消引用类型的punned指针将打破严格的别名规则
- 字符*转换和混叠规则
- 多重强制转换规则C++
- 显式类型转换vs使用类型规则
- g++和Visual Studio中方法指针强制转换规则之间的差异
- size_t除以int类型转换规则