【发布时间】:2013-11-07 07:13:10
【问题描述】:
这是如何工作的?
struct {
int a : 21;
int b : 11;
};
a 和 b 是两个独立的 int 变量还是使用不同位域的同一个变量?
【问题讨论】:
标签: c bit-fields
这是如何工作的?
struct {
int a : 21;
int b : 11;
};
a 和 b 是两个独立的 int 变量还是使用不同位域的同一个变量?
【问题讨论】:
标签: c bit-fields
这是struct 中的两个独立变量,一个名为a,一个名为b。但是,它们的大小使得 a 应该有 21 位,b 应该有 11 位。访问一个变量并对其进行操作不会影响另一个变量。
希望这会有所帮助!
【讨论】:
struct s { int x; char y; };,它在大多数系统上使用 8 个字节。
:21 和 :11 只是限制了您可以分配给此变量的最大值。
int ab=a<<11+b.
a 和 b 打包到一个 32 位实体中? C 标准要求将连续字段打包到实现使用的任何单元中,如果它们完全适合的话。 (如果它们不适合,则标准允许将一个字段部分打包在一个单元中,部分打包在下一个单元中,或者保留未使用的位。)
这里的“变量”是什么意思并不完全清楚。如果您的意思是可以获取地址的内存,那么位域不符合描述,因为它们是“可寻址存储单元”的一部分。如果“变量”是指“我可以在其中存储一些值的位集”,那么 a 和 b 看起来就像结构中的任何其他字段。
不过,足够的语义吹毛求疵了。让我们去源头:
C99 standard 中的 ch 6.7.2.1 说:
10 一个实现可以分配任何大的可寻址存储单元 足以容纳一个位域。如果有足够的空间,一个位域 紧跟在结构中的另一个位域之后应打包 到同一单元的相邻位。如果剩余空间不足, 是否将不适合的位域放入下一个单元或 重叠相邻单元是实现定义的。的顺序 一个单元内的位域分配(高阶到低阶或 低阶到高阶)是实现定义的。对齐方式 可寻址存储单元未指定。
因此,根据编译器选择的“可寻址存储单元”,您的 a 和 b 可能最终位于不同的“存储单元”中,具体取决于编译器的具体情况。
【讨论】:
它的实现方式取决于系统架构。如果你举一个更直接的例子:
struct x {
uint8_t a : 2;
uint8_t b : 3;
};
这里a 和b 可能会共享相同的内存字节,例如:xxxb bbaa(其中 x 未使用)。
我相信对齐和打包的语义是未定义的 - 最好尝试一下!如果您正在做一个多平台项目,请注意不同的硬件(甚至可能是编译器)。
struct x s;
s.a = 3;
s.b = 5;
printf("0x%02X\n", *((char*)&s) );
输出可能是0x03、0x05、0x16 甚至0x25。
我希望看到0x16...
在我看来,在传输位域时,您应该始终手动构建已知状态。
uint8_t buf[];
buf[x] = 0;
buf[x] |= (s.a) & 0x03;
buf[x] |= (s.b << 2) & 0x1C;
【讨论】: