现在的位置: 首页 > 综合 > 正文

了解#pragma pack(n)

2013年08月10日 ⁄ 综合 ⁄ 共 1899字 ⁄ 字号 评论关闭

    早上看书,看到#pragma pack(n),不甚了解,果断学习之,留点心得体会,大家一起讨论讨论

 

例子,一般的题目主要是问sizeof(S1)是多少:

 

1.当n大于结构体最长的数据类型的长度时(如例子当中的int),这个n就宣布没有任何影响了

2.计算大小和补字节时从前往后计算,对齐按数据类型和n值当中的小的值进行,如char是1,如果n是4的话,那么以1做对齐,当加入一个新的成员时,这个成员的起始偏移必须是其对齐值的整数倍.好吧,比较抽象,举例来说,假设n=4,如S1,算大小时这么算,首先是m1,m1是char,一个字节,用1个字节对齐,加上m2时,m2是short,两个字节,那么此时,m2的起始偏移是2,偏移是从0算起的.此时就需要补一个字节[m1,00,(m2,m2)],进而加入m4,刚好是4个字节,同时起始偏移是4,很好,接下来3个char,最后由于以4对齐,所以还要补多一个字节,总的结构体的长度是12.如果n=8,那么8>int的长度,所以结构体以4个字节进行对齐.如果n=1,就是要求不做对齐处理,结构体长度为10.

3.当结构体当中存在结构体成员,那么结构体成员按他的长度参与对齐,比如我现在有个S2的结构,里面有个S1结构的成员,如果我声明S1的时候n=1,那么在S2里面S1以10的长度参与对齐,如果声明S1的n=4,那么S2里面,S1以长度12对齐.需要注意的是,S1结构体的成员以几个字节的形式对齐要看n值与S1的int谁比较小.这个注意点主要是在判断内部成员内存位置的时候需要用到.

 

有个题目我觉得分析的不错,附上给大家

-----------------------------------------------我是分割线--------------------------------------------------


1.sizeof(s2) = ?
2.s2的c后面空了几个字节接着是d?

 

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的内存布局:11**,1111,
                          c    S1.a S1.b     d
S2的内存布局:1***,11**,1111,****11111111

这里有三点很重要:
1.每个成员分别按自己的方式对齐,并能最小化长度
2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度
3.对齐后的长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐

补充一下,对于数组,比如:
char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐.
如果写: typedef char Array3[3];
Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度.
不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个.

抱歉!评论已关闭.