包装结构
默认情况下,结构用 C 填充。如果要避免此行为,则必须明确请求它。在 GCC 下,它是 __attribute__((__packed__))
。在 64 位计算机上考虑此示例:
struct foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
long x; /* 8 bytes */
};
该结构将自动填充到 has8-byte
对齐,如下所示:
struct foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
char pad[7]; /* 7 bytes added by compiler */
long x; /* 8 bytes */
};
所以 sizeof(struct foo)
会给我们 24
而不是 17
。这是因为 64 位编译器在每个步骤中以 8 字节的字对存储器进行读/写操作,并且当尝试在存储器中写入 char c;
时,显而易见的是一个完整的 8 字节(即字)取出并仅消耗第一个字节它及其七个连续的字节保持为空,并且对于结构填充的任何读写操作都不可访问。
结构包装
但是如果添加属性 packed
,编译器将不会添加填充:
struct __attribute__((__packed__)) foo {
char *p; /* 8 bytes */
char c; /* 1 byte */
long x; /* 8 bytes */
};
现在 sizeof(struct foo)
将返回 17
。
通常使用包装结构:
- 为了节省空间。
- 格式化数据结构以通过网络传输,而不依赖于网络的每个节点的每个架构对齐。
必须考虑到某些处理器(如 ARM Cortex-M0)不允许未对齐的内存访问; 在这种情况下,结构打包可能导致未定义的行为并可能导致 CPU 崩溃。