pyt*_*hon 3 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;
};
Run Code Online (Sandbox Code Playgroud)
我正在用这种方式检查大小:
int main(void) {
printf("%zu\n", sizeof(struct stc));
}
Run Code Online (Sandbox Code Playgroud)
并编译:
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.
};
Run Code Online (Sandbox Code Playgroud)
这很奇怪所以我试图解决这个问题,我知道这个联盟似乎是0号.
struct stc {
union stc2 {
long a0;
int a1;
int a2;
};
Run Code Online (Sandbox Code Playgroud)
sizeof(struct stc) == 0
.我认为这是因为编译器优化?如果是这样,如何将其关闭?如果没有,为什么?另一个问题当然是如何正确计算这个结构的大小(有或没有优化)以及为什么这个简单结构的大小:
struct stc {
char arr[10];
};
Run Code Online (Sandbox Code Playgroud)
是10而不是12.我认为如果你不说编译器没有对齐值,那么每个值都与4,8,12,16,20等对齐.
所以你在这里有很多问题.我去的时候会回答一些问题:
你给了代码:
struct stc {
union stc2 {
long a0;
int a1;
int a2;
};
};
Run Code Online (Sandbox Code Playgroud)
请注意,您在结构中声明了没有变量.您可能打算执行以下操作,其大小可能与之相同sizeof(long)
.
struct stc {
union stc2 {
long a0;
int a1;
int a2;
} x;
};
Run Code Online (Sandbox Code Playgroud)
所以,让我们试着找出来自哪里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
};
Run Code Online (Sandbox Code Playgroud)
所以看起来很合适.
struct stc {
char arr[10];
};
Run Code Online (Sandbox Code Playgroud)
因此,每种类型都有一个大小和对齐要求.因为char
,这两者都是1.因为uint32_t
它们通常都是4.但是根据架构,对齐可能不同.
所以在这种情况下,结构的任何元素的最大对齐需求stc
是1.因此整个结构的对齐要求仍然是1
,即使大小是10
.
一般来说,您希望添加大小所需的填充,以便声明struct stc x[2]
将导致所有元素正确对齐.
因此,您可以在此处执行一些操作来帮助了解编译器正在执行的操作.
在堆栈溢出时发布有关内存布局的问题时,使用中定义的类型非常有用stdint.h
.这些包括类似int32_t
和int16_t
.这些更好,因为对于什么尺寸没有混淆long
.
您可以使用offsetof工具来确定编译器放置成员的位置.您可以在此处了解有关如何使用它的更多信息.
这是一个非常简单的结构示例,它具有编译器必须插入的大量填充.
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)
};
Run Code Online (Sandbox Code Playgroud)