如果我定义一个char变量
char a;
和具有单个char成员的结构
struct OneChar {
char a;
};
这两个定义在所有编译器中的大小都是'char'吗? 我怀疑的是,如果我们在结构中定义一个char变量,由于内存打包它会比char的大小更大吗?
答案 0 :(得分:6)
这取决于架构和编译器。对于这种特殊情况,您应该是安全的,但请查看Data Structure Padding。
这是excerpt:
x86上C结构的典型对齐
存储数据结构成员 按顺序存储在内存中 成员Data1下面的结构 将始终位于Data2和Data2之前 将始终位于Data3之前:
struct MyData { short Data1; short Data2; short Data3; };
如果“短”类型存储在两个中 然后每个成员的内存字节 上面描述的数据结构 将是2字节对齐。 Data1会 偏移量为0,偏移量为2的数据2和 偏移量为4的Data3。大小 结构将是6个字节。
每个成员的类型 结构通常有默认值 对齐,意思是它会, 除非另有要求 程序员,对齐 预先确定的边界。下列 典型的比对有效 来自Microsoft,Borland和。的编译器 编译32位x86时的GNU:
- char(一个字节)将以1字节对齐。
- 短(两个字节)将是2字节对齐。
- int(四个字节)将是4字节对齐。
- 一个浮点数(四个字节)将是4字节对齐的。
- 双重(8字节)将在Windows上对齐8字节,在Linux上对齐4字节。
这是一个成员的结构 各种类型,总共8个字节 汇编
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个字节 添加到最后一个成员来填补 结构到长字的大小。
可以更改对齐方式 减少记忆的结构 他们需要(或符合 现有格式)通过改变 编译器的对齐(或“打包”) 结构成员。
请求MixedData 上面的结构与一个结构对齐 字节边界将具有编译器 丢弃预先确定的对齐 的成员和没有填充字节 会被插入。
虽然没有标准的方法 定义结构的对齐 成员,一些编译器使用#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等等 其他
答案 1 :(得分:1)
只要有一个成员,我认为你的假设是安全的。
答案 2 :(得分:1)
您列出的案例将在我知道的所有ABI下打包为1字节结构。
但是如果你需要移植处理更复杂的情况,最佳做法是在计算内存大小时始终使用sizeof(struct OneChar)
,并在需要通过如下技巧计算地址时获取字段地址的偏移量: / p>
(char*)&(((struct OneChar*)0)->a) - (char*)0
答案 3 :(得分:0)
所有a
s都具有相同的大小,无论它们是独立的还是在结构内。
结构内部可能发生的是成员之间存在填充......但这也可能发生在“独立”变量中。
答案 4 :(得分:0)
当你获取结构的大小时,它包含填充字节。但是,如果您有以下内容:
void fun()
{
char c;
int n;
}
编译器可以根据它看到的任何原因自由插入填充。因此,在独立变量的情况下,填充可能就在那里,你只是在结构的情况下无法知道它。
答案 5 :(得分:0)
各种编译器将优化以在结构之间或结尾处添加填充。因此,在所有编译器或平台上假设分配的大小看起来并不安全。检查编译器选项以设置struct padding。
例如,Visual Studio使用#pragma pack
指令覆盖默认优化。