gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 16:12:15 25 4
gpt4 key购买 nike

我正在尝试计算此结构的字节大小并有几个问题

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.
};

这很奇怪,所以我试图弄清楚这个问题,我知道这个 union 的大小似乎是 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 等对齐。

最佳答案

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

sizeof 结构为零?

您提供了代码:

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,即使大小是 10

一般来说,您希望为大小添加任何必要的填充,这样声明 struct stc x[2] 会导致所有元素正确对齐。

建议

因此,您可以在这里做一些事情来帮助了解您的编译器正在做什么。

  1. 在堆栈溢出时发布有关内存布局的问题时,使用 stdint.h 中定义的类型非常有帮助。其中包括 int32_tint16_t 等类型。这些更好,因为不会混淆 long 的大小。

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

虽然可以发生填充:

这是一个非常简单的结构示例,其中包含编译器必须插入的大量填充。

struct x {
uint64_t x; // Offset 0, Size 8
char y; // Offset 8, Size 1
// Offset 9, Size 1 (Padding)
uint16_t z; // Offset 10, Size 2
// Offset 12, Size 4 (Padding)
};

关于c - 具有 union 和位域的结构的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25962248/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com