uint12 结构中的字节序
Endianness within uint12 struct
假设我有数据,如下所示:
union
{
struct
{
char flags : 4;
uint16_t : 12;
}
char data[2];
}
我了解如何使此代码运行,而不管平台上的字节字节序如何。我要求确保我对如何在不同的字节序上存储它的理解是正确的。
据我了解: 如果我在 12 位 uint 中存储一个 uint16,两个字节序都会丢弃 4 个最高位。Big-endian 会将剩余的 4 个高位存储在与标志相同的字节中,其余的存储在单独的字节中。Little-endian 会将 4 个最低位存储在与标志相同的字节中,其余的存储在单独的字节中。
这是对的吗?
这取决于编译器和目标平台的 ABI。例如,请参阅GCC位域的规则:单元内位字段的分配顺序由ABI确定。此外,每个字段都应该声明为int
或unsigned int
,而不是uint16_t
。
如果要控制数据格式,可以使用移位和掩码将数据组合成uint16_t
。如果您的目标是以明确定义的格式写出数据,则可以以所需的字节序写入uint16_t
字节,或者只是将数据组合成 2 个字节并按所需的顺序写入它们。
除非你找到承诺你想要的语言规范文档,或者你的编译器文档做出了明确的承诺,并且你对大端和小端 CPU 使用相同的编译器,否则不要依赖 C/C++ 编译器都以相同的方式做这样的事情。
Little-endian 会将 4 个最低位存储在与标志相同的字节中
我熟悉的所有编译器只有在它们的基本存储单元相同时才组合相邻的位域(尽管其中一个可爱的实现定义细节)。因此,在您的示例中,将char
与uint16_t
混合会破坏将它们组合在一起,这意味着该结构将使用 3 个字节(对于任一字节序)。对两个字段使用相同的基本类型可以得到你想要的(但static_assert(sizeof(...) == 2)
以防万一):
union
{
struct
{
uint16_t flags : 4;
uint16_t value : 12;
}
uint8_t data[2];
}
每个位布局为:
字节 LE 顺序 | BE 顺序#1 BE 顺序# | 2 | |||
---|---|---|---|---|---|
0 | F0 V8 | V4 | |||
0 | 1 | F1 V9 | V5 | ||
0 | 2 | F2 | VA | V6 | |
0 | 3 | F3 | VB | V7 | |
0 | 4 V0 | F0 | V8 | ||
0 | 5 | V1F1 | V9 | ||
0 | 6 | V2 F2 | VA | ||
0 | 7 V3 | F3 | VB | ||
8 | 1 | 0 | V4 V0 | F0 | |
9 | 1 1 | V5 | V1 F1 | ||
10 | 1 | 2 | V6 V2 | F2 | |
11 | 1 3 | V7 V3 | F3 | ||
12 | 1 4 | V8 V4 | V0 | ||
13 | 1 5 | V9 V5 | V1 | ||
14 | 1 | 6 | VA | V6 V2 | |
15 | 1 | 7 | VB | V7 V3 |
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- DNS 查询格式标头结构中的小字节序问题
- 哪些值存储在对齐的结构/类对象的填充字节中
- 为什么这个结构需要 24 个字节
- 正在转换结构数据的字节序
- 在C++中更改整个结构的字节序
- 使用字节数组具有单字节对齐方式的结构是否安全
- 在字节数组上转换具有虚函数的结构是否安全?
- 为什么标准库不以无锁的方式为 8 字节以下的结构实现 std::atomic?
- 将结构中的字节数组传递给 com 对象
- 为什么在未由语言本身定义的结构字节中的位字段顺序
- C 将5个字节结构与Cacheline保持一致
- C++结构到字节*引发错误
- 填充C 中C结构的填充字节?(不关心结构包装!)
- 将结构添加到字节向量,然后添加另一个
- uint12 结构中的字节序
- C 在结构中添加所有字节
- 具有3字节块的序列化C 结构
- 使用指针访问结构的各个字节
- MSVC 2008 16字节结构成员对齐奇怪