linux 32平台下默认对齐方式为:
- char 按照字节对齐2. short 按照2字节对齐
- int,long等其他基本类型按照4字节对齐
为了让结构体数组中的每一个结构体内部元素都保持对齐,编译器会在结构体的末尾插入gap以满足结构体内部元素的对齐要求。结构体的地址对齐按照结构体中包含的最大字节数元素对齐,以满足结构体数组的对齐要求。
或者根据原理:pack pragma
pack pragma设置了struct、union或class中各成员的对齐方式,结构成员对齐指的是成员相对于起始地址的偏移量。该指令基本用法如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
```
它指定了结构成员按n(1,2,4,8,16)(alignment must be a small power of 2)字节对齐,如果未指定n,则恢复成默认值。需要注意的是,它并不是指结构体中的每个成员都要按n对齐,而是 按照每个成员的大小和n相比较小的值对齐。下面引用MSDN中C++ Preprocessor Reference部分关于pack指令的说明:
n (optional)
Specifies the value, in bytes, to be used for packing. The default value for n is 8. Valid values are 1, 2, 4, 8, and 16. The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.
即成员member的对齐值
align of member = min( pack setting value, sizeof(member type) )
>
这里的pack是编译器结构体对齐的字节数,默认是4字节,可以通过#pargma pack(n)
进行调整(#pargma unpack() 回复到原来),boxsize 也就是每个成员对齐的盒子大小,
计算时成员所占内存大小必须是这个boxsize的整数倍,
`box_size=min{pack,max{sizeof(member type)} } `注意这里的sizeof(memeber type) 是成员的基本类型比如:char a[10],应该是sizeof(char) 而不是sizeof(a[10])
编译器每次只取一个盒子大小的内存,如果当前盒子不够又会在再取一个盒子的大小:
```c
struct A
{
int a;
int b;
short s;
char c;
};
sizeof(A)=12分析:
1
2
3box_size=min{pack(4),max(sizeof(member))}
=min{4,4}
=4因为编译器先取一个盒子放a,刚好用完已取内存接着再拿一个盒子大小的内存放b也刚好用完,接着再取一个,发现存放s之后还有2个字节,接着与c大小比较,结果也能够存储c。所以size=12。所以我们应该尽量将不能是box_size大小的成员放在一起,以节省内存。
上面的例子如果调换一下b和s的位置那么sizeof=16例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56struct ch{
char c;
}; //sizeof ch = 1
printf("Sizeof ch =%d\n",sizeof (ch));
struct ch2{
char c;
char cc;
};//sizeof ch2 = 2
printf("Sizeof ch2 =%d\n",sizeof (ch2));
struct size{
char c;
short s;
}; //sizeof size = 4
printf("Sizeof size1=%d\n",sizeof (size));
struct size{
char c;
char cc;
short s;
};//sizeof size = 4
printf("Sizeof size2=%d\n",sizeof (size));
struct size{
char c;
short s;
char cc;
};//sizeof size = 6
printf("Sizeof size3=%d\n",sizeof (size));
struct size{
char c;
char cc;
int i;
};//sizeof size = 8
printf("Sizeof size4 =%d\n",sizeof (size));
struct size{
char c;
int i;
char cc;
}; //sizeof size = 12
printf("Sizeof size5=%d\n",sizeof (size));
struct size{
char c;
char cc;
int i;
struct ch ich;
};//sizeof size = 12
printf("Sizeof size6=%d\n",sizeof (size));
struct size{
char c;
char cc;
struct ch ich;
int i;
};sizeof size = 8
printf("Sizeof size7=%d\n",sizeof (size));运行结果:
Sizeof ch =1
Sizeof ch2 =2
Sizeof size1=4
Sizeof size2=4
Sizeof size3=6
Sizeof size4 =8
Sizeof size5=12
Sizeof size6=12
Sizeof size7=8
当结构体中出现结构体类型的数据成员是,不会将嵌套的结构体类型的整体长度参与到对齐计算中,而是以嵌套定义的结构体锁使用的对齐值进行对齐。
eg:
1 | struct tagOne |