请提供需要翻译的内容。
此外,在其他作用域中定义的结构/联合体的任何其他实例,在使用联合体时会产生更大的堆栈分配,但在使用结构体时不会扩大堆栈分配。
现在,这没有意义——联合体应该占用更少的堆栈空间,如果有的话,而不是与具有相同字段的结构体一样多!
似乎GCC即使在不同的范围内使用联合体时也将其视为同时使用,但对于结构体则不做同样的处理。
还有一些澄清:
1. volatile用于防止编译器优化赋值。去掉volatile并进行无优化编译会产生相同的结果。
2. 即使testme是一个具有联合体成员之一的结构体,也会观察到相同的行为。换句话说——只要结构体的一个成员是联合体,GCC就会为不同的堆栈分配分别分配堆栈。
3. 编译器是gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5),但其他架构的GCC版本显示了相同的行为。
4. checkstack.pl只是搜索objdump输出以查找用于分配堆栈(向堆栈指针的sub)的指令。
我的问题:
1. GCC为什么要这样做?这是个错误还是这种行为有原因?
2. 假设这不是一个错误,是否有一种方法可以解决这个问题,并强制GCC像联合体一样为结构体分配堆栈。
澄清:我的问题不是为什么结构体或联合体的大小似乎比其部分的大小要大。我理解原因是用于对齐的填充。我的问题是编译器即使在不同的作用域中定义了多个联合体实例,也会为它们分配多个堆栈帧,而对于具有相同字段的结构体确实不会这样做。
谢谢!
#include <stdlib.h>
#ifndef TRY
#define TRY struct
#endif
TRY testme
{
int one;
int two;
char three;
int four;
};
int
main (void)
{
{
volatile TRY testme one;
one.one = 2;
one.three = 7;
}
{
volatile TRY testme twos;
twos.one = 3;
}
{
volatile TRY testme one;
one.one = 4;
}
{
volatile TRY testme twos;
twos.one = 5;
}
{
volatile TRY testme twos;
twos.one = 6;
}
{
volatile TRY testme twos;
twos.one = 6;
}
return EXIT_SUCCESS;
}
在x86编译时(也就是说testme是一个结构体),编译器为main函数分配的栈大小为16字节。
$ gcc -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
16 main
然而,如果定义了TRY为union(意味着testme是一个union),编译器为main分配的堆栈大小为32字节:
$ gcc -DTRY=union -g -O2 test.c -o test
$ objdump -d ./test | ./checkstack.pl i386 | grep main
此外,在其他作用域中定义的结构/联合体的任何其他实例,在使用联合体时会产生更大的堆栈分配,但在使用结构体时不会扩大堆栈分配。
现在,这没有意义——联合体应该占用更少的堆栈空间,如果有的话,而不是与具有相同字段的结构体一样多!
似乎GCC即使在不同的范围内使用联合体时也将其视为同时使用,但对于结构体则不做同样的处理。
还有一些澄清:
1. volatile用于防止编译器优化赋值。去掉volatile并进行无优化编译会产生相同的结果。
2. 即使testme是一个具有联合体成员之一的结构体,也会观察到相同的行为。换句话说——只要结构体的一个成员是联合体,GCC就会为不同的堆栈分配分别分配堆栈。
3. 编译器是gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5),但其他架构的GCC版本显示了相同的行为。
4. checkstack.pl只是搜索objdump输出以查找用于分配堆栈(向堆栈指针的sub)的指令。
我的问题:
1. GCC为什么要这样做?这是个错误还是这种行为有原因?
2. 假设这不是一个错误,是否有一种方法可以解决这个问题,并强制GCC像联合体一样为结构体分配堆栈。
澄清:我的问题不是为什么结构体或联合体的大小似乎比其部分的大小要大。我理解原因是用于对齐的填充。我的问题是编译器即使在不同的作用域中定义了多个联合体实例,也会为它们分配多个堆栈帧,而对于具有相同字段的结构体确实不会这样做。
谢谢!