保证用于序列化目的的reinterpret_cast输出
guarantee of reinterpret_cast output for serialization purpose
int main()
{
char buffer[5] = { 0 };
buffer[0] = 23;
std::string s(&buffer[0], 4);
std::uint32_t nb = *reinterpret_cast<const std::uint32_t*>(s.data());
return 0;
}
对于此程序,reinterpret_cast的输出实现是否取决于?还是任何符合 c++ 标准的编译器总是产生相同的输出?
对于您的示例代码,如果您正在寻找"任何符合 c++ 标准的编译器始终产生相同的输出"的东西,答案是没有这样的保证。
几个简单的例子:对齐问题(如几条评论所述(和字节序差异。
C++11 5.2.10/7 "重新诠释演员表"说:
对象指针可以显式转换为 不同的类型。当类型为"指向
T1
的指针"的 prvaluev
转换为类型"指向 CVT2
的指针",结果为static_cast<cv T2*>(static_cast<cv void*>(v))
T1
和T2
是否都是标准布局 类型(3.9(和T2
的对齐要求不比T1
的那些,或者如果任一类型是void
。转换类型的 prvalue "指向T1
的指针"到"指向T2
的指针"类型(其中T1
和T2
位于 对象类型以及T2
的对齐要求为否 比T1
的更严格,并返回到其原始类型,产生 原始指针值。任何其他此类指针的结果 未指定转换。
由于uint32_t
通常比char[]
有更严格的对齐要求,因此该标准不对行为做出任何承诺(因为上面只讨论了满足对齐要求的情况(。所以严格来说,行为是不确定的。
现在,假设您只对满足对齐要求的平台感兴趣(即,uint32_t
可以在任何地址上对齐,与char
相同(。然后,涉及重新解释强制转换的表达式等效于(请注意,您还必须从从std::string::data()
返回的const char*
中丢弃const
(:
std::uint32_t nb = *(static_cast<std::uint32_t*>(static_cast<void*>(const_cast<char*>(s.data()))));
该标准在 5.2.9/13 "静态强制转换"中对对象指针使用static_cast
(类层次结构中的指针之间的转换除外(是这样说的:
因此,就类型为">指向 cv1
void
的指针"的 prvalue 可以转换为 prvalue 类型"指向 CV2T
的指针",其中T
是对象类型,CV2 是 简历资格与简历1相同,或比CV1更高。这 空指针值将转换为 目标类型。指向对象的指针类型的值转换为 "指向 cvvoid
的指针"和返回,可能具有不同的 简历资格,应有其原始价值。
标准而言,您对生成的指针所能做的就是将其转换回去以获取原始值。其他任何东西都是未定义的行为(实现可能会提供更好的保证(。
3.10/10 "左值和右值"也允许通过char
或unsigned char
类型访问对象。
但是,重申一下:该标准不保证"任何符合c ++标准的编译器始终产生相同的输出"对于您发布的示例。
您正在强制std::uint32_t
一个缓冲区,该缓冲区不一定与此类值正确对齐。
这可能会爆炸和/或效率极低。
无符号整数类型意味着值表示位的任何位模式都是可以的,并且在内置类型的PC平台上,除了值表示位之外没有其他位;特别是没有陷阱位或捕获总位模式。
因此,你可以做一个memcpy
,从技术上讲,你会没事的——只要有足够的字节,s.length() >= sizeof(std::uint32_t)
.
但是,如果这种转换发生在普通代码中,则会产生强烈的代码气味,表明设计中存在根本性错误。
附录,关于"或者一个尊重 c++ 标准的编译器将始终产生相同的输出"。
当我回答时,我不知何故没有看到这一点。但简短的回答是,如果转换以有效的方式执行,例如使用 memcpy
,那么它取决于字节序,在实践中是将整数的最有效部分还是最不重要的部分放在最低地址。
实际上,您可以使用从网络字节顺序转换为的面向网络的函数。只需假设序列化数据的网络字节顺序。查看ntohl
等人(这些不是C++标准库的一部分,但通常可用(。
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Shared_ptr cast vs static_cast speed
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C++ C++ 中的函数声明,键入 CAST
- static_cast会丢弃错误,但C风格的演员cast有效
- C++ cast char * to unsigned char
- 禁用 Clang 中的"cast from pointer to smaller type uint32_t"错误
- 是否可以使用gcc 3.3版修复与int*cast相关的Sun Solaris OS 5.8分段故障
- C++ const-cast 一个引用