下面这个篇博客讲解很好

http://blog.csdn.net/meegomeego/article/details/9393783

总的来看分三类:

1. 不加 #pragma pack(n)伪指令(n未对齐的字节数目)

2. 加#pragma pack(n) 伪指令

3. __attribute__((aligned(n)))来使用n个字节方式的对齐

 

第一种:不加 #pragma pack(n)伪指令

对其的字节数目为一个结构体中的基本类型(int char float double,特别强调复合型(数组、结构体、联合体)不算。)成员变量中最大的字节数(也可理解为默认对齐字节数,如char 默认 1字节 int 默认 4字节 等)。

第二种:加#pragma pack(n) 伪指令

对其的字节数目为一个结构体中的基本类型(int char float double,特别强调复合型(数组、结构体、联合体)不算。)成员变量最大的字节数(也可理解为默认对齐字节数,如char 默认 1字节 int 默认 4字节 等)pragma pack(n) 中的n值二者之间的较小数为对齐的字节数。比如:一个结构体中基本类型的

成员变量为 float a;//默认是4字节对齐,而加#pragma pack(8) 设置为8字节,此时加#pragma pack(8)设置失效,是4字节对齐(4 < 8),如果 n 为 2,那么对齐的字节数就是2字节了(2 < 4)。

经典例子:

 1 // 例3(如果在GCC中编译,请加上-malign-double选项)  
 2 #pragma pack(8)  
 3 struct s1  
 4 {  
 5     short a; // 第一个成员,放在[0, 1]偏移的位置。  
 6     long  b; // 第二个成员sizeof(long)=4, #pragma pack(8), 取小值也就是4  
 7          // 所以这个成员按4字节对齐,放在偏移[4~7]的位置。  
 8 };  
 9     // struct s1中size最大的数据成员(4), #pragma pack(8)  
10     // 取小值也就是4,所以sizeof(struct s1)应当按照4来对齐,为8  
11   
12 struct s2  
13 {  
14     char      c; // 第一个成员,放在[0]偏移的位置。  
15     struct s1 d; // 第二个成员为struct s1,其对齐方式是它的所有成员使用的对齐参数中最大的一个,即4。  
16              // 所以第二个成员d按4字节对齐,由于sizeof(d)=8, 放在偏移[4~11]的位置。  
17     long long e; // 第三个成员sizeof(long long)=8, #pragma pack(8), 取小值也就是8  
18              // 所以这个成员按8字节对齐,放在偏移[16~23]的位置。  
19 };  
20 #pragma pack()  
View Code

第三种:__attribute__((aligned(n)))来使用n个字节方式的对齐

这种方式和第二种的方式是刚好相反的,取得是较大值来作为字节对齐。

经典例子:

 1 #include <stdio.h>  
 2 #include <stdlib.h>  
 3   
 4 #pragma pack(16)  
 5 struct testa  
 6 {  
 7         unsigned int number;  
 8 };  
 9 #pragma pack()  
10 struct testa arr_testa[4] = { {65535}, {65535}, {65535}, {65535} };  
11   
12 struct testb  
13 {  
14         unsigned int number;  
15 } __attribute__ ((aligned (16))) ;  
16   
17 struct testb arr_testb[4] = { {65535}, {65535}, {65535}, {65535} };  
18   
19   
20 int main(int argc, const char *argv[])  
21 {  
22         printf("sizeof(struct testa) = %d, sizeof(arr_testa) = %d\n",  
23                         sizeof(struct testa), sizeof(arr_testa));  
24         printf("sizeof(struct testb) = %d, sizeof(arr_testb) = %d\n",  
25                         sizeof(struct testb), sizeof(arr_testb));  
26   
27         printf("address of arr_testa[0] = %p\n", &arr_testa[0]);  
28         printf("address of arr_testa[1] = %p\n", &arr_testa[1]);  
29         printf("address of arr_testa[2] = %p\n", &arr_testa[2]);  
30         printf("address of arr_testa[3] = %p\n", &arr_testa[3]);  
31         puts("");  
32         printf("address of arr_testb[0] = %p\n", &arr_testb[0]);  
33         printf("address of arr_testb[1] = %p\n", &arr_testb[1]);  
34         printf("address of arr_testb[2] = %p\n", &arr_testb[2]);  
35         printf("address of arr_testb[3] = %p\n", &arr_testb[3]);  
36         return 0;  
37 }  
View Code

输出结果为:

 1 sizeof(struct testa) = 4, sizeof(arr_testa) = 16  
 2 sizeof(struct testb) = 16, sizeof(arr_testb) = 64  
 3 address of arr_testa[0] = 0x804a040  
 4 address of arr_testa[1] = 0x804a044  
 5 address of arr_testa[2] = 0x804a048  
 6 address of arr_testa[3] = 0x804a04c  
 7   
 8 address of arr_testb[0] = 0x804a060  
 9 address of arr_testb[1] = 0x804a070  
10 address of arr_testb[2] = 0x804a080  
11 address of arr_testb[3] = 0x804a090 
View Code

 特别强调注意union 的字节对齐:

1 union AAA{
2   double i;//8B
3        int  k[5];//20B
4        cahr b; //1B 
5 }
View Code

上面的unionAAA类型,类型的字节大小为sizeof(AAA) ,按固有的原则来看,应该取AAA中长度最长的成员的程度。但是容易忽略一点就是字节对齐问题。综合考虑union类型的字节大小的求解,从如下两方面入手:

1. 找到占内长度最大的成员

2. 考虑字节对齐问题

union  AAA:

1. k[5] 占内存20字节最大

2. 最长的基本类型成员为double类型,占据8字节。故最后union AAA占用内存应该是8的倍数,20 + 4 即可

sizeof(AAA)  = 24字节!

posted on 2016-07-26 10:20  人生一世,草木一秋。  阅读(7)  评论(0编辑  收藏  举报