C位域 结构体的大小

3
#include <stdio.h>
int main() {
    struct on_off {
        unsigned light      : 1;
        unsigned toaster    : 1;
        int count;/* 4 bytes */
        unsigned ac         : 4;
        unsigned            : 4;
        unsigned clock      : 1;
        unsigned            : 0;
        unsigned flag       : 1;
    } kitchen;
    struct box_props {
         unsigned int opaque       : 1;
         unsigned int fill_color   : 3;
         unsigned int              : 4; 
         unsigned int show_border  : 1;
         unsigned int border_color : 3;
         unsigned int border_style : 2;
         unsigned int              : 2; 
    } s;

    printf("\n\nSize of struct on_off = %d\n", sizeof(struct on_off));
    printf("\nSize of box_props = %d\n", sizeof(struct box_props));

    return 0;
}

在编译这个程序时,struct on_off 的大小报告为 16,而 box_props 的大小报告为 4。有人能解释一下为什么会发生这种情况吗?

1
也许是因为它容易对齐吧?顺便说一下,通过将错误类型的数据传递给 printf() 你调用了 未定义行为 。应该使用 %zu 而不是 %d 打印从 sizeof 运算符返回的 size_t - MikeCAT
3个回答

4

对于第一种结构

struct on_off{
    unsigned light      : 1;
    unsigned toaster    : 1;  // 1 byte 
                              // 3 bytes - packing to align to int border
    int count;                // 4 Bytes        
    unsigned ac         : 4;
    unsigned ss         : 4;  // 1 Byte
    unsigned clock      : 1;  // 1 byte
    unsigned            : 0;  // 2  byte -- A size of zero forces alignment to next boundary.
    unsigned flag       : 1;  // 1 byte
                              // 3 bytes -- Packing at end of struct to align to word boundary.
}
                              // 16 bytes -- Total

第二个结构如下:
struct box_props{
     unsigned int opaque       : 1;
     unsigned int fill_color   : 3;
     unsigned int              : 4;   // 1 byte
     unsigned int show_border  : 1;
     unsigned int border_color : 3;   // 1 byte
     unsigned int border_style : 2;   
     unsigned int              : 2;   // 1 byte
                                      // 1 byte - packing at the end of structure to align to word boundary.
}
                                      // 4 bytes Total

1
默认情况下,C结构体和C++类不是紧凑的。因此,在成员变量 count 之前会添加额外的填充位,使其对齐到int边界。(并且结构体在结尾处也会填充到字边界。)
除此之外,unsigned : 0 实际上告诉编译器在该字段处将结构体对齐到int边界。参见: 零长度位域的实际用途 因此,sizeof(struct on_off) 将为4个整数。如果删除 unsigned : 0,则为3个整数。
如果想要进行紧凑排列,则需要使用 pack 声明或 packed/aligned 属性。请参见:#pragma pack effect"__attribute__((packed, aligned(4)))" 的含义是什么?

-1
尺寸的差异是由Rishikesh Raje在他的答案中概述的填充和对齐规则造成的,但是您的代码行为可能未定义,因为您正在将size_t类型的值传递给printf格式%d。 如果您的编译器支持,则应更改格式为标准格式:
printf("\nSize of struct on_off = %zu\n", sizeof(struct on_off));
printf("\nSize of box_props = %zu\n", sizeof(struct box_props));

或者使用强制类型转换以提高可移植性,适用于不支持C99的环境,例如Microsoft Visual Studio:

printf("\nSize of struct on_off = %d\n", (int)sizeof(struct on_off));
printf("\nSize of box_props = %d\n", (int)sizeof(struct box_props));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接