位字段结构分配意外行为
Bit fields struct assignment unexpected behaviour
我不知道为什么,但位字段分配没有按预期工作。可能只是一件愚蠢的事情,但我无法找到问题所在。
任何帮助都非常受欢迎。
typedef struct a {
unsigned char a1 :1;
unsigned char a2 :3;
unsigned char a3 :2;
unsigned char a4 :2;
} __attribute__((packed)) mystruct;
int main() {
mystruct d;
d.a1 = 0;
d.a2 = 2;
d.a3 = 1;
d.a4 = 2;
unsigned char *val = (unsigned char*) &d;
printf("%02X n", *val);
printf("%02X n", sizeof(hola));
exit(0);
}
返回的输出:
94
01
预期输出:
26
01
几乎所有关于位字段的内容都是实现定义的。尤其是单位中位数的顺序。
(在实现中,位C99,6.7.2.1p10)"单元内位字段的分配顺序(高阶到低阶或低阶到高阶)是实现定义的。
首先存储在单位 lsb(最低有效位)中,而不是像预期的那样首先存储在 msb(最高有效位)中。
你拥有的是:
[a1.0] [a2.0] [a2.1] [a2.2] [a2.0] [a3.1] [a4.0] [a4.1]
0 0 1 0 1 0 0 1
bit 0 - bit 7
lsb - msb
如果您认为最左边的位是最不重要的位,这是0x94
的。
ASCII 艺术:
MSB LSB
+----+----+----+----+----+----+----+----+
|a4.1|a4.0|a3.1|a3.0|a2.2|a2.1|a2.0| a1 |
+----+----+----+----+----+----+----+----+
| 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
+----+----+----+----+----+----+----+----+
| 0x9 | 0x4 |
+----+----+----+----+----+----+----+----+
如前所述,行为是实现定义的;这是组织数据的两种合法方式之一,似乎是在您的机器上选择的格式。 另一种行为是。
MSB LSB
+----+----+----+----+----+----+----+----+
| a1 |a2.2|a2.1|a2.0|a3.1|a3.0|a4.1|a4.0|
+----+----+----+----+----+----+----+----+
| 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
+----+----+----+----+----+----+----+----+
| 0x2 | 0x6 |
+----+----+----+----+----+----+----+----+
这显然是您所期望的行为。
由于它是实现定义的,因此您可以查看手册并找到编译器的功能,因为编译器必须记录其行为。
如果你有可移植性需要担心,你将需要考虑如何组织你的结构定义,以你需要的方式在你使用的每个平台上工作。
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 在C++中对T*类型执行std::move的意外行为
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- 处理除以零会导致<csignal>意外行为
- 在班级中使用动态分配的C风格字符串,并带有复制和分配操作员,给出了意外的结果
- 意外分配
- 位字段结构分配意外行为
- C++分配的指针显示意外行为