C 结构和相应变量的大小
如果我定义一个char变量C 结构和相应变量的大小,c,C,如果我定义一个char变量 char a; 和具有单个char成员的结构 struct OneChar { char a; }; 在所有编译器中,这两个定义的大小是否都与“char”相同? 我的疑问是,如果我们在结构中定义一个char变量,由于内存压缩,它需要的大小会大于char的大小吗?只要有一个成员,我认为您可以放心地假设。这取决于体系结构和编译器。对于这种特殊情况,您应该是安全的,但请检查 这是一个: x86上C结构的典型对齐方式 存储数据结构成员 按顺序存储在内存中,以便 成员数据1
char a;
和具有单个char成员的结构
struct OneChar {
char a;
};
在所有编译器中,这两个定义的大小是否都与“char”相同?
我的疑问是,如果我们在结构中定义一个char变量,由于内存压缩,它需要的大小会大于char的大小吗?只要有一个成员,我认为您可以放心地假设。这取决于体系结构和编译器。对于这种特殊情况,您应该是安全的,但请检查 这是一个: x86上C结构的典型对齐方式 存储数据结构成员 按顺序存储在内存中,以便 成员数据1下面的结构 将始终位于Data2和Data2之前 将始终位于数据3之前:
struct MyData
{
short Data1;
short Data2;
short Data3;
};
如果类型“short”存储在两个
字节的内存,然后是
上面描述的数据结构
将是2字节对齐的。数据1将
位于偏移量0处,数据2位于偏移量2处,并且
偏移量4处的数据3。这个大小
结构将是6个字节
系统中每个成员的类型
结构通常有一个默认值
对齐,意味着它将,
除非业主另有要求
编程器,在一条直线上对齐
预先确定的边界。以下
典型路线适用于以下情况:
来自Microsoft、Borland和
为32位x86编译时的GNU:
- 字符(一个字节)将按1字节对齐李>
- 短的(两个字节)将是2字节对齐的李>
- int(四个字节)将是4字节对齐的
- 浮点(四个字节)将是4字节对齐的
- 双字节(8字节)在Windows上是8字节对齐的,在Linux上是4字节对齐的
struct MixedData
{
char Data1;
short Data2;
int Data3;
char Data4;
};
在编译数据结构之后
将添加填充物
字节,以确保正确对齐
各成员:
struct MixedData /* after compilation */
{
char Data1;
char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */
short Data2;
int Data3;
char Data4;
char Padding1[3];
};
结构的编译大小为
现在是12字节。注意这一点很重要
最后一个成员用
所需的字节数
符合最大类型的
结构。在这种情况下,需要3个字节
添加到最后一个成员以填充
一个长单词大小的结构
可以更改对齐方式
减少内存的结构
他们要求(或遵守)一个
通过更改
编译器的对齐(或“打包”)
结构件
请求混合数据
上面的结构必须与一个对齐
字节边界将包含编译器
放弃预先确定的对齐方式
的成员,并且没有填充字节
将插入
虽然没有标准的方法
定义结构的对齐方式
各位成员,有些编译器使用#pragma
用于指定内部包装的指令
源文件。以下是一个例子:
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
struct MyPackedData
{
char Data1;
long Data2;
char Data3;
};
#pragma pack(pop) /* restore original alignment from stack */
此结构将具有一个已编译的
大小为6字节。上述指示
在编译器中可以从
微软、Borland、GNU和许多
其他的
所有
a
s将具有相同的大小,无论它们是独立的还是在结构内部
结构内部可能发生的情况是,成员之间存在填充。。。但这种情况也可能发生在“独立”变量中。当您计算结构的大小时,它包括填充字节。但是,如果您有以下情况:
void fun()
{
char c;
int n;
}
编译器可以出于任何原因自由插入填充。因此,在独立变量的情况下,填充可能在那里,你只是不知道这一点,就像在结构的情况下一样。你列出的情况将在我知道的所有ABI下打包为一个1字节的结构 但如果您需要可移植地处理更复杂的情况,最佳做法是在计算内存大小时始终使用
sizeof(struct OneChar)
,并在需要通过以下技巧计算地址时使用字段地址的偏移量:
(char*)&(((struct OneChar*)0)->a) - (char*)0
各种编译器将优化以在结构之间或结构末尾添加填充。因此,在所有的编译器或平台上,假设分配的大小是看起来的大小是不安全的。检查编译器选项以设置结构填充
例如,Visual Studio使用该指令覆盖默认优化。我认为结构中的第一个字段必须位于偏移量0处。另外,在
中有offset of
,它将执行可怕的空指针技巧,因此您不必这样做。我真正的疑问是,在单成员结构中,内存填充是否会起作用?在您的情况下,我不这么认为,但正如我之前所说的,这取决于。我真正的疑问是,在单成员结构中,内存填充会起作用吗?还允许在最后一个成员之后进行填充(不仅仅是在成员之间)。