文章标题 原创 翻译 转载 文章内容 ## 内存对齐的原因 大部分的参考资料都是如是说的: * 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 * 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 ## 内存对齐规则 * 成员的起始位置必须大于先前成员的终止位置,并且是“自身所占字节数”的整数倍; * 如果成员也是结构体,那么这个子结构体的起始位置就是“这个子结构体中的最大成员所占字节数”的整数倍; * 最后,结构体所占内存的字节数必须是“最大成员所占字节数”的整数倍,不足需补齐。 ## 看下面几个例子就清楚了 假设在32位机器上,结构体中第一个成员: 起始位置 = 0,那么终止位置 = 起始位置 + 成员自身所占的字节数。 例子1: ``` typedef struct _AA { char c; // 0 (第一个成员的起始位置为0) int n; // 4 - 7 (int占四个字节) 规则一 short s; // 8 - 9 (short占两个字节,但不是最大成员的整数倍,所以需补齐) 10 - 11 规则三 }AA; // 最后,这个结构体所占字节数就是12 ``` 例子2: ``` typedef struct _CC { char name[2]; // 0 - 1 int id; // 4 - 7 规则一 double score; // 8 - 15 short grade; // 16 - 17 AA aa; // 20 - 31 (本来起始位置是从18开始,但是18并不是最大成员int的整数倍,所以需从20开始) 规则二 }CC; // 最后,所占字节数为32 ``` ## #pragma pack(n) 通过上面这条语句可以改变“对齐系数”,对以上对齐规则的影响是: 规则一中的“自身所占字节数”,规则二中的“这个子结构体中的最大成员所占字节数”,规则三中的“最大成员所占字节数”都要与 “对齐系数n”进行比较,取小者。 例子3: ``` // 不指定对齐系数,即采用默认对齐系数 typedef struct _DD { char c; // 0 double d; // 8 - 15 short s; // 16 - 17 18 - 23 }DD; // 大小是24 ``` 例子4: ``` // 指定对齐系数为4 #pragma pack(4) typedef struct _DD { char c; // 0 double d; // 4 - 11 (double自身字节数是8个字节,与4进行比较,取4的倍数) short s; // 12 - 13 14 - 15 (最大成员字节数8也与4进行比较,补齐时取4的倍数) }DD; // 大小是16 ``` 以上就简单的介绍了一下结构体大小的计算方法,如有不正确的地方欢迎指正。 > 2011-07-09 文章类别 Python Mobile Android Java Shell Life Database Bug Windows IOS Tools Boost Node.js Mac Product Tips C/C++ Golang Javascript React Qt MQ MongoDB Design Web Linux LLM ChatGPT RAG AI 提交