有关bitfield的问题?

时间:2016-07-01 05:24:56

标签: c++

考虑我用union

实现的以下位域
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

为什么union和结构都是4个字节?我只定义了8位,不应该是一个字节吗?如果一个位是“unsigned int”定义的2个字节,那么它不应该是16个字节吗?似乎任何一种思维方式都不起作用。为什么是4个字节?

另外,我注意到我不能做“sizeof(bitByte.bitField.bit0)”,那个大小是多少?我将它定义为一位,但无符号int的定义是2个字节。 bit0,bit1等有多少字节?

6 个答案:

答案 0 :(得分:1)

C标准在6.7.2.1中指定:

  

实现可以分配任何足够大的可寻址存储单元来保存位 -   领域。如果剩余足够的空间,则紧跟在a中的另一个位字段的位字段        结构应打包到同一单元的相邻位。如果剩余空间不足,         是否将不适合的位域放入下一个单元或重叠相邻单元            实现定义。单位内位域分配的顺序(高位到               实现定义的是低阶或低阶到高阶。对齐                可寻址存储单元未指定。

C ++标准在9.6中简洁得多:

  

在类中分配位字段   对象是实现定义的。位字段的对齐是实现定义的。比特字段被打包   进入一些可寻址的分配单位。

这两者的结果是位域总是分配有一些实现定义的分配单元,并且虽然多个位域可以打包在单个分配单元中,但是在结构域中为位域分配的空间将始终是那个分配单位。

没有标准定义的常量或定义的查询分配单元大小的方法,尽管术语&#34;实现已定义&#34;确实意味着实现应该在某个地方记录这个大小。

在您的特定情况下,编译器似乎选择4字节的分配单元,因此大小最终会是什么。不同的编译器可以选择不同大小的分配单元,或者甚至可以让单个编译器为同一程序中的不同结构选择不同大小的分配单元。该规范特别不受限制。

答案 1 :(得分:0)

答案 2 :(得分:0)

  

为什么union和结构都是4个字节?

联盟的大小=最大的成员。

Struct的大小=所有成员的大小总和(带填充)。

所以,在你的代码中 sizeof(bitByte)= sizeof(bitByte.bitField)或sizeof(bitByte.bitField2)

  

我只定义了8位,不应该是一个字节吗?

填充是因为处理器要求某些类型的数据具有特定的对齐。

答案 3 :(得分:0)

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个字节

答案 4 :(得分:0)

你告诉它分配来自底层unsigned int的位,在你的平台上显然是4个字节。

编辑:As Chris Dodd points out,编译器实际上并不需要这样做,但我认为你很难找到一个没有的东西。网络数据包布局在大多数系统中都很重要,因此特定体系结构的所有编译器都会很快适应常规。

答案 5 :(得分:-1)

对于int,它是四个字节,因为struct也给出了4个字节

例如

spring.profiles.active=cache-off,perf-monitoring-on

在这种情况下,您也会为logging.file=prod.log选择 4 字节。