1,比如:
struct{ short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; sizeof( A)=6, sizeof( B)=8,为什么? 注:sizeof(short)=2,sizeof(long)=4
因为:“成员对齐有一个重要的条件,即每个成员按自己的方式对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.”(引用) 结构体A中有3个short类型变量,各自以2字节对齐,结构体对齐参数按默认的8字节对齐,则a1,a2,a3都取2字节对齐,则sizeof(A)为6,其也是2的整数倍; B中a1为4字节对齐,a2为2字节对齐,结构体默认对齐参数为8,则a1取4字节对齐,a2取2字节对齐,结构体大小6字节,6不为4的整数倍,补空字节,增到8时,符合所有条件,则sizeof(B)为8;
可以设置成对齐的 #pragma pack(1) #pragma pack(push) #pragma pack(1) struct{ short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; #pragma pack(pop) 结果为sizeof( A)=6,sizeof( B)=6
************************
2,又如:
#pragma pack(8) struct S1{ char a; long b; }; struct S2 { char c; struct S1 d; long long e; }; #pragma pack() sizeof(S2)结果为24. 成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐. 也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节. S1中,成员a是1字节默认按1字节对齐,指定对齐参数为8,这两个值中取1,a按1字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,所以sizeof(S1)应该为8; S2 中,c和S1中的a一样,按1字节对齐,而d 是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是它的所有成员使用的对齐参数中最大的一个,S1的就是4.所以,成员d就是按4字节对齐.成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时, 已经使用了12个字节了,所以又添加了4个字节的空,从第16个字节开始放置成员e.这时,长度为24,已经可以被8(成员e按8字节对齐)整除.这样, 一共使用了24个字节. a b S1的内存布局:1***, 1111, c S1.a S1.b e S2的内存布局:1***, 1***, 1111, ****11111111
这里有三点很重要: 1.每个成员分别按自己的方式对齐,并能最小化长度 2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐
补充一下,对于数组,比如: char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐. 如果写: typedef char Array3[3]; Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度. 不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个.
转自:http://blog.chinaunix.net/u/11768/showart.php?id=70557
一道关于结构对齐的题目 struct{ short a1; short a2; short a3; }A; struct{ long a1; short a2; }B; 问:为什么sizeof(A)为6,sizeof(B)为8。 这是一个关于结构数据对齐的题,其原因是为了加快CPU的存取速度,编译器在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,叫数据对齐(data alignment)。其对齐规则为:结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。这也就是为什么会出现这个现象的原因。因为sizeof(short)为2,sizeof(int)为4,sizeof(long)也为4。对于开头题目中的Struct B,因为long长为4,short长为2,因为short会补跳成为4,因此为8。而对于Strutc A,每个成员均为2,因此不需要补空字节。 下面另一个例子: #include <stdio.h>
struct{ short a1; short a2; short a3; long a4; }A; struct{ long a1; int a3; }B; int main() { printf("sizeof(short)=%d sizeof(long)=%d sizeof(int)=%d/n", sizeof(short), sizeof(long ), sizeof(int)); printf("sizeof(A)=%d sizeof(B)=%d/n", sizeof(A), sizeof(B)); return 0; } struct A长为12,因为a1和a2一起长度为4,a3为2,long为4,因为需要为a3补空字节,使其长度变为4。 Struct B长为8. 再看另一个结构: struct{ short a1; long a5; short a2; long a6; short a3; long a4; }A; 其长度为24,因为a1长为2,a5长为4,因此a1需要补成4,其余字节同样。 但当我们把struct A调整为 struct{ short a1; short a2; short a3; long a4; long a5; long a6; }A; 其长度就变为20了。 说实在话,这个问题是我以前根本没注意的问题。 但是如果我们在前面加上#pragma pack(1),我们会发现编译不会进行对齐的操作。因为成员对齐有一个重要的条件,即每个成员按自己的方式对齐.其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐.并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节.”
| | | |