我试图计算这个结构的字节大小,并有几个问题
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等对齐。
答案 0 :(得分:5)
所以你在这里有很多问题。我会回答一些问题:
你给了代码:
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
};
所以看起来很合适。
struct stc {
char arr[10];
};
因此,每种类型都有一个大小和对齐要求。对于char
,这两个都是1.对于uint32_t
,它们通常都是4.但是根据架构,对齐方式可能不同。
所以在这种情况下,struct stc
的任何元素的最大对齐需求是1.因此整个struct的对齐要求仍然是1
,即使大小为{{1 }}
一般来说,您希望添加大小所需的填充,以使声明10
能够使所有元素正确对齐。
因此,您可以在此处执行一些操作来帮助了解编译器正在执行的操作。
在堆栈溢出时发布有关内存布局的问题时,使用struct stc x[2]
中定义的类型非常有用。其中包括stdint.h
和int32_t
等类型。这些更好,因为int16_t
的大小没有混淆。
您可以使用offsetof工具确定编译器放置成员的位置。您可以了解有关如何使用它的更多信息here。
这是一个非常简单的结构示例,它具有编译器必须插入的大量填充。
long