字节对齐,还有你不知道的!

字节对齐,还有你不知道的!

  • 空间
 

字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,
如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最
末一个成员之后加上填充字节(trailing padding)。

一、

结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也
在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
这个很厉害,很佩服c语言标准小组里的大牛! 0x00000000指针的妙用!

 

二、

VC6中通过#pragma pack实现,也可以
直接修改/Zp编译开关。#pragma pack的基本用法为:#pragma pack( n ),n为字节对齐
数,其取值为1、2、4、8、16,默认是8,如果这个值比结构体成员的sizeof值小,那么
该成员的偏移量应该以此值为准,即是说,结构体成员的偏移量应该取二者的最小值。

#pragma pack(push) // 将当前pack设置压栈保存
#pragma pack(2)// 必须在结构体定义之前使用

//定义结构体

#pragma pack(pop) // 恢复先前的pack设置

 

还有含有位域的结构体,以及联合体,实在用到的时候再来看看吧。繁琐。

===============================================================

8. 含位域结构体的sizeof
前面已经说过,位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构
体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

9. 联合体的sizeof
结构体在内存组织上是顺序式的,联合体则是重叠式,各成员共享一段内存,所以整个
联合体的sizeof也就是每个成员sizeof的最大值。结构体的成员也可以是复合类型,这
里,复合类型成员是被作为整体考虑的。

posted @ 2017-04-06 10:44  dfdqzp  阅读(173)  评论(0编辑  收藏  举报