结构体内存对齐问题

上传人:子 文档编号:43437372 上传时间:2018-06-06 格式:DOC 页数:8 大小:33.50KB
返回 下载 相关 举报
结构体内存对齐问题_第1页
第1页 / 共8页
结构体内存对齐问题_第2页
第2页 / 共8页
结构体内存对齐问题_第3页
第3页 / 共8页
结构体内存对齐问题_第4页
第4页 / 共8页
结构体内存对齐问题_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《结构体内存对齐问题》由会员分享,可在线阅读,更多相关《结构体内存对齐问题(8页珍藏版)》请在金锄头文库上搜索。

1、结构体内存对齐问题结构体内存对齐问题结构体内存对齐问题.txt 偶尔要回头看看,否则永远都在追寻,而不知道自己失去了什么。男人掏钱是恋人关系,女人掏钱是夫妻关系,男女抢着掏钱是朋友关系。男人爱用眼睛看女人,最易受美貌迷惑;女人爱用心看男人,最易受伤心折磨。当在 C 中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C 对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密。首先,至少有一点可以肯定,那就是 ANSI C 保证结构体中各字段在内存中出现的位

2、置是随它们的声明顺序依次递增的,并且第一个字段的首地址等于整个结构体实例的首地址。比如有这样一个结构体:struct vectorint x,y,z; s;int *p,*q,*r;struct vector *ps;p = q = r = ps = assert(p |- array3 ._| | | | | a | b | a | b |.| | | | |+-Bytes: 4 1 4 1当数组首地址是 4 字节对齐时,array1.a 也是 4 字节对齐,可是 array2.a 呢?array3.a .呢?可见这种方案在定义结构体数组时无法让数组中所有元素的字段都满足对齐规定,必须修改成

3、如下形式:_| | | a | b |padding| | |+-+Bytes: 4 1 3现在无论是定义一个单独的 MS2 变量还是 MS2 数组,均能保证所有元素的所有字段都满足对齐规定。那么 sizeof(MS2)仍然是 8,而 a 的偏移为 0,b 的偏移是 4。好的,现在你已经掌握了结构体内存布局的基本准则,尝试分析一个稍微复杂点的类型吧。typedef struct ms3char a;short b;double c; MS3;我想你一定能得出如下正确的布局图:padding |_v_| | | | a | b |padding| c | | | |+-+Bytes: 1 1 2

4、 4 8sizeof(short)等于 2,b 字段应从偶数地址开始,所以 a 的后面填充一个字节,而 sizeof(double)等于 8,c 字段要从 8 倍数地址开始,前面的 a、b 字段加上填充字节已经有 4 bytes,所以 b 后面再填充 4 个字节就可以保证 c 字段的对齐要求了。sizeof(MS3)等于 16,b 的偏移是 2,c 的偏移是 8。接着看看结构体中字段还是结构类型的情况:typedef struct ms4char a;MS3 b; MS4;MS3 中内存要求最严格的字段是 c,那么 MS3 类型数据的对齐模数就与 double 的一致(为 8),a 字段后面应

5、填充 7 个字节,因此MS4 的布局应该是:_| | | a |padding| b | | |+-+Bytes: 1 7 16显然,sizeof(MS4)等于 24,b 的偏移等于 8。在实际开发中,我们可以通过指定/Zp 编译选项来更改编译器的对齐规则。比如指定/Zpn(VC7.1 中 n 可以是 1、2、4、8、16)就是告诉编译器最大对齐模数是 n。在这种情况下,所有小于等于 n字节的基本数据类型的对齐规则与默认的一样,但是大于 n 个字节的数据类型的对齐模数被限制为 n。事实上,VC7.1 的默认对齐选项就相当于/Zp8。仔细看看 MSDN 对这个选项的描述,会发现它郑重告诫了程序员

6、不要在 MIPS 和 Alpha 平台上用/Zp1 和/Zp2 选项,也不要在 16 位平台上指定/Zp4 和/Zp8(想想为什么?)。改变编译器的对齐选项,对照程序运行结果重新分析上面 4 种结构体的内存布局将是一个很好的复习。到了这里,我们可以回答本文提出的最后一个问题了。结构体的内存布局依赖于 CPU、操作系统、编译器及编译时的对齐选项,而你的程序可能需要运行在多种平台上,你的源代码可能要被不同的人用不同的编译器编译(试想你为别人提供一个开放源码的库),那么除非绝对必需,否则你的程序永远也不要依赖这些诡异的内存布局。顺便说一下,如果一个程序中的两个模块是用不同的对齐选项分别编译的,那么它

7、很可能会产生一些非常微妙的错误。如果你的程序确实有很难理解的行为,不防仔细检查一下各个模块的编译选项。思考题:请分析下面几种结构体在你的平台上的内存布局,并试着寻找一种合理安排字段声明顺序的方法以尽量节省内存空间。A. struct P1 int a; char b; int c; char d; ;B. struct P2 int a; char b; char c; int d; ;C. struct P3 short a3; char b3; ;D. struct P4 short a3; char *b3; ;E. struct P5 struct P2 *a; char b; struct P1 a2; ;

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号