【问题标题】:Bitfields in C with struct containing union of structsC中的位域,其结构包含结构的联合
【发布时间】:2011-02-20 03:52:02
【问题描述】:

嗯...为什么当我打印 sizeof(struct MyStruct) 时,它会为这段代码输出 3(而不是 2)?

#pragma pack(push, 1)
    struct MyStruct
    {
        unsigned char a : 6;
        union
        {
            struct
            {
                unsigned int b : 9;
            };
        };
    };
#pragma pack(pop)

以防万一,我在 Windows 7 x64 上运行 MinGW GCC 4.5.0,但老实说,结果对我来说已经够奇怪了,我认为编译器和操作系统在这里并不重要。 :\

【问题讨论】:

    标签: c struct unions bit-fields


    【解决方案1】:

    您不能让字段以非字节对齐的地址开始。 你期待:

    6 bits + 9 bits -> 15 bits -> 2 bytes
    

    但你得到的是:

    6 bits -> 1 byte
    9 bits -> 2 bytes
    total ->  3 bytes
    

    数据存储为:

    | 1 byte | 2 byte |3 byte | 
     aaaaaaXX bbbbbbbb bXXXXX  
    

    你期待的时候:

    | 1 byte | 2 byte |
     aaaaaabb bbbbbbbX  
    

    编辑: 根据以下cmets进行澄清:

    联合(和包含的结构)必须是字节对齐的。内容只有 9 位没关系,联合/结构本身就是一个完整的 16 位。请注意,您不能执行以下操作:

    struct MyStruct
    {
        unsigned char a : 6;
        union
        {
            struct
            {
                unsigned int b : 9;
            } c:9;
        } d:9;
    };
    

    因为 C 不允许您指定整个结构的位大小。

    【讨论】:

    • 是的,但为什么呢?它们不是字节对齐的位字段的全部意义吗? (并不是说两个相邻的 1 位字段都是字节对齐的,所以这有什么不同呢?)
    • 哈哈,这是一个公平的观点。这真的取决于实现。你的编译器在做什么: struct MyStruct { unsigned char a : 6;无符号整数 b:9; }; ?
    • 它给出了一个 2...(否则位字段不会毫无意义吗?)
    • 是的。 :) 这是因为结构和/或联合。我相信您的编译器要求那些从字节对齐的地址开始。我刚刚尝试过:codepad.org/xWbrGP1g ... 请注意,无论 codepad.org 使用什么编译器,其行为都类似(尽管似乎需要字对齐)。同样,它依赖于实现。澄清一下,结构本身必须占据完整的 int 大小。
    • 嗯,我的意思是,我看到 什么 发生了对齐,但是问题是“为什么?”还在我脑海里挥之不去。比如,为什么结构应该是字对齐的,如果它有位域?这在任何情况下都有什么好处,或者这只是没有充分理由的任意要求?
    【解决方案2】:

    补充@nss 给出的答案——我很抱歉,如果 cmets 在格式方面没有受到如此限制,这将是一个评论:

    #include <stdlib.h>
    
    struct Test {
      unsigned short x : 6;
      unsigned short y : 1;
      unsigned short z;
    };
    
    int main( int argc, char *argv[] ) {
      printf( "sizeof( Test ) = %d\n", sizeof( struct Test ) );
    
      return 0;
    }
    

    它打印“4”作为大小。我用 gcc、g++ 和 Sun Studio 的 CC 和 cc 进行了测试。

    并不是我建议你做你想做的事情,但你可能会做你想做的事情。我见过(但不是我自己写的)代码看起来像这样:

    struct Test {
      unsigned short x1 : 6;
      unsigned short x2 : 3;
                        : 1; // unused
      unsigned short x3 : 4;
      // ...
    };
    

    我的语法可能有点错误……但我不这么认为。

    要点:使用您要使用的布局创建两个单独的结构(或一个结构和一个联合),然后在它们应该重叠的地方插入一些虚拟成员,并将它们联合在一起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-21
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多