拿来即用的线程池聊聊
可以看出都是对齐到4字节。并且前面的char和short并没有被凑在一起(成4字节),这和结构体内的处理是不同的。 至于为什么输出的地址值是变小的,这是因为该平台下的栈是倒着“生长”的。 3.3 位域对齐 3.3.1 位域定义 有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间和处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。 位域是一种特殊的结构成员或联合成员(即只能用在结构或联合中),用于指定该成员在内存存储时所占用的位数,从而在机器内更紧凑地表示数据。每个位域有一个域名,允许在程序中按域名操作对应的位。这样就可用一个字节的二进制位域来表示几个不同的对象。
位域定义与结构定义类似,其形式为: 变量b自身对齐值为1,指定对齐值为2,所以有效对齐值为1,假设C从0x0000开始,则b存放在0x0000,符合0x0000%1= 0;变量a自身对齐值为4,指定对齐值为2,所以有效对齐值为2,顺序存放在0x0002~0x0005四个连续字节中,符合0x0002%2=0。变量c的自身对齐值为2,所以有效对齐值为2,顺序存放在0x0006~0x0007中,符合0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。C的自身对齐值为4,所以其有效对齐值为2。又8%2=0,C只占用0x0000~0x0007的八个字节。所以sizeof(struct C) = 8。
注意,结构体对齐到的字节数并非完全取决于当前指定的pack值,如下: 3.1.3.3 排查对齐问题 如果出现对齐或者赋值问题可查看: 编译器的字节序大小端设置; 处理器架构本身是否支持非对齐访问; 如果支持看设置对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。 3.1.4 更改对齐方式 主要是更改C编译器的缺省字节对齐方式。 在缺省情况下,C编译器为每一个变量或是数据单元按其自然对接条件分配空间。一般地,可以通过下面的方法来改变缺省的对接条件: 使用伪指令#pragma pack(n):C编译器将按照n个字节对齐; 使用伪指令#pragma pack(): 取消自定义字节对齐方式。 另外,还有如下的几种方式(GCC特有语法): __attribute((aligned (n))): 让所作用的结构成员对齐在n字节自然边界上。如果结构体中有成员的长度大于n,则按照最大成员的长度来对齐。 __attribute__ ((packed)):取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。 【注】__attribute__机制是GCC的一大特色,可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。 下面具体针对MS VC/C++ 6.0编译器介绍下如何修改编译器默认对齐值。 VC/C++ IDE环境中,可在[Project]|[Settings],C/C++选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认是8字节。 VC/C++中的编译选项有/Zp[1|2|4|8|16],/Zpn表示与n字节边界对齐。n字节边界对齐是指一个成员的地址必须安排在成员的尺寸的整数倍地址上或者是n的整数倍地址上,取它们中的最小值。亦即:min(sizeof(member), n)。实际上,1字节边界对齐也就表示结构成员之间没有空洞。 /Zpn选项应用于整个工程,影响所有参与编译的结构体。在Struct member alignment中可选择不同的对齐值来改变编译选项。 在编码时,可用#pragma pack动态修改对齐值。具体语法说明见附录5.3节。 自定义对齐之后要用#pragma pack()来还原,否则会对后面的结构造成影响。
【例3】分析如下结构体C: (编辑:南通站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |