#pragma pack 定义变量的起始存放地址对齐方式

之前一直习惯手动对齐struct数据存放地址,比如一个struct中有3个变量,分别是char型,short型,int型,本人比较习惯的这样定义结构体:

typedef struct
{
    int i;
    short j;
    char k;
    char ver;            
}

前面3个是要定义的实际变量,第四个是为了补齐4字节对齐手动添加的一个无关变量;

最近阅读代码偶然遇到个陌生的对齐形式格式如下:

#pragma pack(show)
#pragma pack(push,4)

#pragma pack(pop)

之前只知道#pragma pack(n)是指定对齐方式,但是如上的书写形式还是比较陌生,故详细查了查资料,深入了解了一番;其实这种形式也是用来指定变量在内存中的存放起始地址对齐方式,只不过是对齐之前把之前的对齐方式保存起来而已;而

#pragma pack(show)只是用来在编译器里显示当前的对齐方式,(主要是提示给当前程序员看的,编译代码的时候可以在log上的警告信息里看到当前的编译环境设置的对齐方式)

具体用法如下:

1 #pragma pack(push,n) // 保存当前系统设置的对齐方式,压入堆栈,然后设置当前对齐方式为n字节对齐,n通常取 1 2 4 8
2 
3 .........
4 
5 #pragma pack(pop) // 恢复当前的对齐方式

 

pack对齐方式:选当前数据类型本身占用字节数与pack指定的对齐字节数两者之间的最小值, 用这个最小值的整数倍作为存放的起始地址。

 

例1:

1 #pragma pack(push,4)
2  typedef struct test
3  {
4      char j;
5      short x;
6      int i;
7  }node;
8 #pragma pack(pop)

 

 

此时char本身是单字节变量,pack是按照4字节对齐,这两者之间最小值是1,故按照1字节的倍数算起始地址存放变量j,存放在内存 ram[0]中,j占用1个字节;
下一个元素short x 本身是2字节的变量,pack是4字节对齐,按照取这两者中最小数的倍数做起始地址,所以取2的倍数做起始地址放short x,上一个元素char占用了0地址,只占用了单个字节,2的倍数只能是char再填充一个值后再存放short x,故short x 从ram[2]开始存,占用2字节;
int i本身占用4字节,pack要求4字节对齐,故只要满足存放的起始地址是4的倍数即可,前面2个元素分别占用了ram[0]-ram[3],故int i从ram[4]开始算起始地址,往后存放4字节。
 
所以这个结构体总共占用8字节。

例2:

1 #pragma pack(push,2)
2 typedef struct test
3 {
4     char j;
5     short x;
6     int i;
7 }node;
8 #pragma pack(pop)

 

这个结构体也是占用8字节
 
char本身是单字节变量,pack要求2字节对齐,取这两者中最小值的整数倍做起始地址,故取1的最小整数倍做起始地址存放char j,存放在ram[0],占用1个字节;
short x本身是双字节变量,pack要求2字节对齐,故只要是2的整数倍就可以做为起始地址,前面的变量只占用了ram[0]空间,ram[1]不是2的整数倍,所以取下一个地址ram[2]作为存放起始地址,short x存放于ram[2]-ram[3]占用2字节
int i本身是4字节变量,pack要求2字节对齐,故只要是2的整数倍就可以作为起始存放地址,ram[4]正好是2的整数倍,故存放在ram[4]-ram[7]共占用4字节。
posted @ 2017-08-09 14:45  迷途小菜鸟  阅读(1200)  评论(0编辑  收藏  举报