具有union和位域的结构的大小

时间:2014-09-21 18:01:14

标签: c struct sizeof memory-alignment bit-fields

我试图计算这个结构的字节大小,并有几个问题

struct stc {
    int a;
    int b;
    char c;
    union stc2 {
        long a0;
        int a1;
        int a2;
    };
    char arr[10];
    int z:2;
};

我以这种方式检查尺寸:

int main(void) {
    printf("%zu\n", sizeof(struct stc));
}

并编译:

gcc -std=c99 -m32 -Wall -Wextra test.c

它是gcc 4.9和我在64位计算机上,但首先要尝试使用32位值,因此-m32。现在,结果是20,但我不知道为什么会这样。这就是我的计算方法。

struct stc {     
    int a;        // +4 = 4
    int b;        // +4 = 8
    char c;       // +1 but next is long, so +4 (alignment) = 12
    union stc2 {
        long a0;  // +4 = 16
        int a1;
        int a2;
    };
    char arr[10]; // +8 (for arr[8]) and 2 bits left = 24 (or 28)
    int z:2;      // +4 = 28 (or 32) 
                  // I'm not sure how it'll work with 2 bits left from char array and
                  // 2 bits from int, so that why I count 2 different values. 
};

这很奇怪,所以我试图解决这个问题,我知道这个联盟似乎是0号。

struct stc {
    union stc2 {
        long a0;
        int a1;
        int a2;
    };

sizeof(struct stc) == 0。我认为这是因为编译器优化?如果是这样,如何将其关闭?如果没有,为什么? 另一个问题当然是如何正确计算这个结构的大小(有或没有优化)以及为什么这个简单结构的大小:

struct stc {
    char arr[10];
};

是10而不是12.我认为如果你没有说编译器没有对齐值,那么每个值都与4,8,12,16,20等对齐。

1 个答案:

答案 0 :(得分:5)

所以你在这里有很多问题。我会回答一些问题:

sizeof struct为零?

你给了代码:

struct stc {
    union stc2 {
        long a0;
        int a1;
        int a2;
    };
};

请注意,您在结构中声明了没有变量。您可能打算执行以下操作,其大小可能与sizeof(long)相同。

struct stc {
    union stc2 {
        long a0;
        int a1;
        int a2;
    } x;
};

位域布局

所以,让我们试着找出20的来源。首先,让我们重新设置没有union没有做任何事情的类型(参见上一个标题)。

另外,请注意,具有位域的结构不需要以与普通类型相同的方式布局在内存中。但是,不管怎样,让我们​​做一些猜测。

struct stc {
    int a;        // Offset 0,  Size 4
    int b;        // Offset 4,  Size 4
    char c;       // Offset 8,  Size 1
    char arr[10]; // Offset 9,  Size 10
    int z:2;      // Offset 19, Size 1-ish
};

所以看起来很合适。

sizeof没有四舍五入到12?

struct stc {
    char arr[10];
};

因此,每种类型都有一个大小和对齐要求。对于char,这两个都是1.对于uint32_t,它们通常都是4.但是根据架构,对齐方式可能不同。

所以在这种情况下,struct stc的任何元素的最大对齐需求是1.因此整个struct的对齐要求仍然是1,即使大小为{{1 }}

一般来说,您希望添加大小所需的填充,以使声明10能够使所有元素正确对齐。

推荐

因此,您可以在此处执行一些操作来帮助了解编译器正在执行的操作。

  1. 在堆栈溢出时发布有关内存布局的问题时,使用struct stc x[2]中定义的类型非常有用。其中包括stdint.hint32_t等类型。这些更好,因为int16_t的大小没有混淆。

  2. 您可以使用offsetof工具确定编译器放置成员的位置。您可以了解有关如何使用它的更多信息here

  3. 虽然可以发生填充:

    这是一个非常简单的结构示例,它具有编译器必须插入的大量填充。

    long