使用位域输出结构大小

时间:2011-06-16 08:04:47

标签: c++ c

#pragma pack(2)
struct a{
  unsigned a:1;
  unsigned b:1;
  int c;
  unsigned d:4;
  unsigned :4;
  unsigned e:1;
  unsigned :0;
  unsigned f:1;} ;

int main()
{
    printf("%d",sizeof(struct a));
}

当使用pragma pack时,以下程序的输出为16,但在使用pragma pack时为10.请解释这是怎么回事?

2 个答案:

答案 0 :(得分:5)

首先,#pragma是特定于编译器的,所以如果不指定编译器和CPU(可能还有编译器版本和命令行选项),我们只能推测。

但是,一个似是而非的解释是,对于“pack(2)”版本:

#pragma pack(2)
struct a{ 
    unsigned a:1;    // at byte offset 0, could be least- or most-significant bit
    unsigned b:1;    // also in byte 0, besides a
    int c;           // explicitly requested this int be mis-aligned at byte 2
                     //   seems you've 32-bit ints, so 4-byte are 2,3,4,5
    unsigned d:4;    // at byte 6
    unsigned :4;     // also fits in byte 6
    unsigned e:1;    // in byte 7
    unsigned :0;     // requests following field be aligned for unsigned type
                     //   your unsigned int must be 32-bits, so this means
                     //   following field must start at 0, 4, 8, 12 etc.
                     //   so: skips rest of byte 7 and moves to 8
    unsigned f:1;    // occupies one bit of byte 8
};

因为打包是“2”,并且已经使用了[0]到[8]中的9个字节,所以sizeof(a)被舍入到10。

没有你的编译指示,默认值是4字节/ 32位。因此,第一个int在32位地址上对齐,以便更快地访问,跳过2和3并占用字节4,5,6,7。这将e推送到这两个跳过的字节在字节9中,:0强制后面的字段在字节12中。然后将总大小四舍五入为32位字大小,因此从13(对于字节[0]到[12]),向上到16岁。

答案 1 :(得分:4)

#pragma pack(2)的效果纯粹是实现定义的,所以 你真的应该阅读有关它的文档(但我可以 猜测)。没有pragma,根据标准,存在 非位域元素或大小为0的位域会导致编译器 前进到下一个“单位”,因此在您的结构中,ab位于 第一个单元,第二个单元c,第三单元de,以及f 第四。鉴于大小是16,我猜4个字节单位(即 今天几乎普遍)。使用#pragma pack(2),我猜是的 基本单位是两个字节,而不是四个。而这并没有改变 int的大小,因此c仍然是四个字节,但其他单位 以上只有两个。这总共给出了十个字节,所以我的猜测 可能并不太远。