结构体的字节对齐问题
遵循的规则:
-
某数据类型的变量存放的地址需要按有效对齐字节剩下的字节数可以被该数据类型所占字节数整除,char可以放在任意位置,int存放在剩下字节数可以被4整除的位置。这个对齐规则是内部一定的
-
结构体的大小一定要为有效对齐值的整数倍
-
当没有明确指明时,以结构体中最长的成员的长度来对齐,注意!数组成员个数并不影响有效对齐值,只是数组类型大小和其他成员比较取最大。但是当然数组成员总占用内存也要遵循字节对齐
-
当用#pragma pack(n)指定时,以n和最长成员中长度较小的值来对齐
-
当用
__attribute__((__n__))
指明时,强制按照该值来对齐
-
类似:char f1:3 这样的语句是位结构,就是本来char类型是占用一个字节,但是现在让char型的f1只占用3位。所以:
sizeof(CVTE)=8,由于C,V这里都是4位,T为8位,合起来为2个字节,为了字节对齐,E只能放在可以被4整除的地址,所以剩下的2并不能被整除,所以要补齐2,再放E,所以一共8个字节。
典型例子:
- 例1:
结果并不是9,由于最后的大小要为int(max)的整数倍,所以是12
- 例2:
由于2<4,所以按2对齐。所以1+1+2+2+1=7,要为2的倍数,所以结果为8
如果指定的pack为8,那么还是按4来对齐,所以结果为12了
- 例3:
不用比较大小了,就是按8对齐。所以1+3+4+1+7=16
- 例4:
最大成员数值并不是8,由于数组的比较数据类型,所以最大的还是4,按4对齐。所以1+3+4*2+4+4=20,可以被4整除。如果这里数组的总大小是9,那么没有和自己数据类型对齐,所以要补齐数组大小为12.
需要内存对齐的原因:
- 平台原因:某些平台只能在特定的地址处访问特定类型的数据
- 性能原因:
- 数据结构应该尽可能在自然边界上对齐
- 访问未对齐的内存,处理器需要作两次内存访问。而对齐的内存仅需要访问一次