预处理指令#pragma pack详解
#pragma pack的大致作用即为改变编译器的对齐方式,先从指令和定义上来分析其功能。
部分内容参考http://www.cnblogs.com/King-Gentleman/p/5297355.html 以及MSDN。
简单理解#pragma
作为较为复杂的预处理指令之一,它的作用为更改编译器的编译状态以及为特定的编译器提供特定的编译指示,这些指示是具体针对某一种(或某一些)编译器的,其他编译器可能不知道该指示的含义又或者对该指示有不同的理解,也即是说,#pragma的实现是与具体平台相关的。可以简单将其理解为该预处理指令是开发者和编译器交互的一个工具。
#pragma pack指令说明
由于内存的读取时间远远小于CPU的存储速度,这里用设定数据结构的对齐系数,即牺牲空间来换取时间的思想来提高CPU的存储效率。
这里先说编译器的对齐配置。以vc6为例,vc6中的编译选项有 /Zp[1|2|4|8|16] ,/Zp1表示以1字节边界对齐,相应的,/Zpn表示以n字节边界对齐。n字节边界对齐的意思是说,一个成员的地址必须安排在成员的尺寸的整数倍地址上或者是n的整数倍地址上,取它们中的最小值。也就是:
min ( sizeof ( member ), n)
实际上,1字节边界对齐也就表示了结构成员之间没有空洞。
/Zpn选项是应用于整个工程的,影响所有的参与编译的结构。
要使用这个选项,可以在vc6中打开工程属性页,c/c++页,选择Code Generation分类,在Struct member alignment可以选择。
而如果要专门针对某些结构定义使用对齐选项,可以使用#pragma pack编译指令。指令语法如下: #pragma pack( [ show ] | [ push | pop ] [, identifier ] , n )
指令用法说明:
- pack提供数据声明级别的控制,对定义不起作用;
- 调用pack时不指定参数,n将被设成默认值;
- 一旦改变数据类型的alignment,直接效果就是占用memory的减少,但是performance会下降。
语法具体分析:
- show:可选参数;显示当前packing aligment的字节数,以warning message的形式被显示;
- push:可选参数;将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈;
- pop:可选参数;从internal compiler stack中删除最顶端的record;如果没有