Q为什么我的编译器在结构体中留下空隙,浪费空间并阻止对外部数据文件的“二进制”I/O?我能否关闭此功能,或以其他方式控制结构体字段的对齐?
A许多机器在访问内存中的值时,如果值已正确对齐,效率最高。(例如,在字节寻址的机器上,short int大小为 2 的 s 最好放在偶数地址,而long int大小为 4 的 s 放在是 4 的倍数的地址上。)有些机器根本无法执行未对齐的访问,并且要求所有数据都必须正确对齐。
因此,如果您声明一个结构体,例如
struct { char c; int i; };编译器通常会在
char
和int
字段之间留出一个未命名、未使用的空隙,以确保int
字段得到正确对齐。(第二个字段基于第一个字段的增量对齐依赖于结构体本身始终正确对齐的事实,具有最保守的对齐要求。编译器会保证它分配的结构体的对齐,而malloc
.)
你的编译器可能提供了一个扩展,让你能够控制结构体的打包(即它们是否被填充),或许使用一个#pragma
(参见问题 11.20),但没有标准方法。
如果您担心空间浪费,可以通过按成员的基本类型从大到小的顺序排列结构体的成员来最小化填充的影响。有时可以通过使用位字段来获得对大小和对齐的更多控制,尽管它们也有自己的缺点。(参见问题 2.26。)
额外链接
关于“对齐”以及为什么需要填充的更多解释
Eric Raymond 关于处理对齐和填充的其他想法,以六个新的 FAQ 列表问题的形式呈现
Norm Diamond 和 Clive Feather 对上述内容的更正
参考:K&R2 第 6.4 节,第 138 页
H&S 第 5.6.4 节,第 135 页