关于位域的问题
Questions about bitfield?
考虑下面我用并集实现的位域
union
{
char fullByte;
struct
{
unsigned int bit0: 1;
unsigned int bit1: 1;
unsigned int bit2: 1;
unsigned int bit3: 1;
unsigned int bit4: 1;
unsigned int bit5: 1;
unsigned int bit6: 1;
unsigned int bit7: 1;
} bitField;
struct
{
unsigned int : 1;
unsigned int bit1to6 : 6;
unsigned int : 1;
} bitField2;
} bitByte;
cout << sizeof(bitByte) << endl; //prints 4
cout << sizeof(bitByte.fullByte) << endl; //prints 1
cout << sizeof(bitByte.bitField) << endl; //prints 4
cout << sizeof(bitByte.bitField2) << endl; //prints 4
为什么联合和结构体都是4字节?我只定义了8位,不是应该是一个字节吗?如果根据unsigned int
的定义,一个比特是2个字节,它不应该是16个字节吗?似乎这两种想法都行不通。为什么是4字节?
同样,我注意到我不能做sizeof(bitByte.bitField.bit0)
,它的大小是多少?我定义它是1位,但unsigned int
是2字节的定义。bit0, bit1等有多少字节?
C标准在6.7.2.1中规定:
实现可以分配任何足够大的可寻址存储单元来容纳位字段。如果仍然有足够的空间,则一个位字段紧跟着另一个位字段结构应装入同一单元的相邻位内。如果剩余空间不足,是否将不匹配的位域放入下一个单元或与相邻单元重叠实现定义。位域在一个单元内的分配顺序(高阶to)低阶或从低阶到高阶)是由实现定义的。的对齐未指定可寻址存储单元。
c++标准在9.6版本中更加简洁:
类中位域的分配对象是实现定义的。位字段的对齐由实现定义。位域被打包到某个可寻址的分配单元
这两种方法的结果是位字段总是用一些实现定义的分配单元来分配的,虽然多个位字段可以打包在一个分配单元中,但在结构体中为位字段分配的空间总是该分配单元的倍数。
没有标准定义的常量或定义的方法来查询分配单元大小是多少,尽管术语"实现定义"确实意味着实现应该在某个地方记录该大小。
在您的特定情况下,似乎编译器选择了4字节的分配单元,所以这就是大小最终是什么。不同的编译器可以选择不同大小的分配单元,甚至单个编译器可以为同一程序中的不同结构体选择不同大小的分配单元。
您告诉它从底层unsigned int
分配位,在您的平台上显然是4个字节。
edit:正如Chris Dodd指出的,编译器实际上并不需要这样做,但我认为你将很难找到一个不这样做的编译器。网络数据包布局在大多数系统上都很重要,因此针对特定体系结构的所有编译器都倾向于很快确定一个约定。
为什么联合和结构体都是4字节?
Union的Size =最大的成员。
Struct的Size =所有成员Size的和(带padding).
那么,在你的代码中sizeof(bitByte) = sizeof(bitByte. bitfield) OR sizeof(bitByte. bitfield2)
我只定义了8位,它不应该是一个字节吗?
填充是因为处理器要求某些类型的数据具有特定的对齐方式。
在union中,分配的总内存空间等于大小最大的成员。所有其他成员共享相同的内存空间。
structure
的大小取决于结构体用来存储变量的bits
的数量。
如果我们要求1 to 32 bits
将变量存储在结构体中,那么在任何情况下,结构体的大小都将是4 bytes
。但是由于需要超过32 bits
(比如33位),那么结构的大小将是8 byte
。这是由于32-bit machine is 4 bytes
上的自然对齐。当数据类型自然对齐时,CPU将在最小的读周期内获取它。因此,结构的大小将是4字节到32位的要求。但是如果我们想要存储33个变量,那将需要33位,那么它将需要两个内存读取周期……即. .8个字节
for int它是4字节的原因结构体也给出了4字节
例如
struct
{
unsigned int bit0: 1;
unsigned int bit1: 1;
unsigned int bit2: 1;
unsigned int bit3: 1;
} bitField;
在这种情况下,您还将为struct
闸门4字节。
- C++Union/Struct位域的实现和可移植性
- 具有位域的结构的 Constexpr 构造函数
- 如何解释 #if/#else 位域?(VC++菜鸟)
- 枚举位域和聚合初始化
- 在有符号基础类型枚举的位域上溢出
- 如何检查位域是否跨越所有位
- 访问位域联合是C++标准中常见的初始数据未定义行为
- 锈迹位域和枚举C++样式
- C/C++:uint8_t位域的行为不正确且不一致
- 如何将位域写入二进制文件
- 字节序和大小为 1 的位域
- 面向对象编程 - 位域私有结构的公共参考
- 使用位域的结构大小不正确
- 在 mingw 的 gcc-5.3 下具有混合位域和枚举递减的结构的意外大小
- 如何将位域成员的所有位设置为 1
- 带有 C++ 位域的匿名 typedef 的前向声明
- 通过套接字C++发送时,位域值会更改
- 有符号的 int 会中断较大位域的某些部分
- Boost日志非常量位域编译错误(向后兼容性问题)
- 关于位域的问题