-
在工作中经常会遇到字节对齐的问题,特别是在一些有通信模块的代码中,经常会看到使用结构体作类型的数据,经过强制的转换,变成字节数组,放到缓冲区中,在打包和解包的是过程中,非常方便。
通常也会遇到这样一些问题,数据明明要发送的是15个字节,却发送了16个字节出去,初学者排查这种问题也是非常痛苦,通常需要爬很多的坑。实际上多的一些字节,通常都是由于空白填充带来的0x00字节。这种问题一般叫做对齐问题,引起相邻两数据类型之间多了一些空白字节。
在C语言中,一般来讲每种数据类型都有自己的对齐要求,比如short一般要两字节对齐,int四字节对齐,long long的八字节对齐。对齐的主要目的就在于加快数据处理的速度,对于32位的cpu,数据总线一般为32位,那么读取对齐的int数据,一般只需要一次,而非对齐的int数据,就需要两次,无形中增加了程序运行的时间,也因此有一些处理器在处理非对齐的数据时,在运行过程中直接bus error,让人非常头痛,在数据数据类型指针进行强制转换时,就要特别注意这种问题。对齐的问题,在一般的数据类型中并不明显,主要还是在结构体中体现,如在下结构体中:
struct data{
char a;
int b;
}
若在四字节对齐时,sizeof(struct data) 为8;若一字节对齐,则sizeof(struct data)为5。四字节对齐时,offset为0的位置放置a,其后空余3个字节,最后放置b,所以一共8个字节。同时在如下结构体中:
struct data{
int b;
char a;
}
若在四字节对齐时,sizeof(struct data) 为8;若一字节对齐,则sizeof(struct data)为5。四字节对齐时,offset为0的位置放置a,其后空余3个字节,最后放置b,所以一共8个字节。同时在如下结构体中:
因此在结构体中,其占内存大小必须是其最大数据类型所占字节的整数倍。
在结构体中,若有结构体类型作为其成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。如下面结构体:
struct data1{
char a;
int b;
}
struct data2{
char c;
struct data1;
}
则结构体成员data1的起始地址必须是4的整数倍。
另外如果提供了#pragma pack指令,则对齐地址按伪指令和结构体内部最大数据类型对齐地址大小的最小值执行
。