C语言字节对齐总结

很久不用#pragma pack(n), 查了一下资料,发现之前的知识点儿好多都记不清楚了,趁热写下总结,以便查询。
#pragma pack(n)作用就是设置编译器按照n字节对齐,可以根据自己的喜好设置编译器的字节对齐方式,也可以设置成1节省空间。
但是,这行代码也不是说设置了n就一定按照n来对齐,有一定的规则:
1)数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2)指定对齐值:#pragma pack (value)时的指定对齐值value。
3)结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
4)数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。
下面结合题目具体分析(vs2013环境):

#pragma pack(8)

struct s1{
short a;
long b;
};

struct s2{
char c;
s1 d;
long long e;
};

#pragma pack()


1.sizeof(s2) = ?
2.s2的c后面空了几个字节接着是d?
sizeof(s2) = 24;
s2的c后面空了3个字节接着是d.
分析:根据规则,c占用了一个字节,然后由s1需要对齐,s1对齐中最大的值为4<8,所以用4,因此c后面空了3个字节,然后是s1,s1内部short占2个字节,然后后面是long,根据规则,short后面空了2个字节,然后是long,总共8个字节是4的整数倍,不需要补齐;然后是long long 8个字节,前面中共占用12个字节,根据对齐规则,需要先空4个字节补齐,然后再占用8个字节,总共((1+3)+(2+2)+(4)+4)+8 = 24,是8的整数倍,所以不需要补齐。由于#pragma pack(8),8比结构中的值都大或者相等,所以这句基本上没起到作用。如果设置位#pragma pack(1),这结果为(1)+(2)+(4)+(8) = 15,这种情况下不需要补齐。
如果把s2中的long long e;去掉,则结果为12,因为此时也是#pragma pack(8)没有起到作用,结构中每个对齐因子都小于8;
如果long long e;后面再定义一个int的变量,则结果为32,需要补齐为8的倍数,但是依然不是#pragma pack(8)的作用,因为s2中long long e;长度为8,int变量是为了和e对齐。
但是,如果上述情况将#pragma pack(8)改为#pragma pack(4),这种情况下,结果为(1+3) +(2+2)+(4)+(8)+4) = 24;

具体占用空间和结构的成员定义顺序也有关系,具体情况需要根据上面的规则具体分析。

你可能感兴趣的:(c,c++基础)