如何合规使用std::bit_cast?含不确定位时的行为界定
含不确定位时std::bit_cast的合规使用与行为界定
我希望了解如何在存在不确定位的情况下合规使用std::bit_cast,明确该操作何时属于定义行为、何时为未定义行为。为此,我需要澄清cppreference中关于std::bit_cast的如下描述含义:
对于结果值表示中每个不确定的位,包含该位的最小对象具有不确定值;除非该对象是
unsigned char或std::byte类型,否则行为未定义。结果不会包含其他不确定值。
当输入(From类型)包含不确定位(尤其是填充位)时,文中提及的对象指什么?unsigned char/std::byte类型与其他类型的区别是什么?
含填充位的示例代码分析
以下为含不确定位的示例代码(非实际用例,仅作场景演示):
#include <bit> #include <cstdint> struct S40 { std::uint8_t a = 0x51; std::uint32_t b = 0xa353c0f1; }; struct S3 { std::uint8_t a : 3; }; int main() { S40 s40; std::uint64_t a64 = std::bit_cast<std::uint64_t>(s40); // (3) 测试编译器中,a64为0xa353c0f1XXXXXX51,其中X为不确定半字节 S3 s3; s3.a = 0b101; std::uint8_t a8 = std::bit_cast<std::uint8_t>(s3); // (4) 测试编译器中,a8为xxxxx101,其中x为不确定位 }
该示例中,我通过调整对齐方式在a和b之间引入填充位(注意clang会向填充位写入垃圾值):
- 生成
a64是否属于未定义行为? - 对于
S3,我模拟了小于1字节且含填充位的类型,生成a8是否属于定义行为(仅值因不确定位而不确定)?
位域相关示例的疑问
另外,附上最初用于区分1字节与其他场景的示例(经指出,该示例无法说明问题,因为将位域传入std::bit_cast会隐式转换为其底层类型的完整定义值):
#include <bit> #include <cstdint> struct S9 { std::uint16_t a : 9; }; struct S7 { std::uint8_t a : 7; }; int main() { S9 s9; s9.a = 42; std::uint16_t a16 = std::bit_cast<std::uint16_t>(s9.a); // (1) a16可能为xxxxxxx000101010,其中x为不确定位 S7 s7; s7.a = 42; std::uint8_t a8 = std::bit_cast<std::uint8_t>(s7.a); // (2) a8可能为x0101010,其中x为不确定位 }
针对该示例,我有如下疑问:
- 文中提及的对象指什么?
- 生成
a8是否属于定义行为(仅值不确定)? - 生成
a16是否属于未定义行为?
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

