为什么会产生数据对齐问题
8位CPU 当然不会产生数据对齐问题,当CPU发展到16,32位时,因为CPU的一次内存访问就能取回4个byte(且用32位举例,这个数据理所当然的缓存在相应的32位寄存器中)——里面可能存储了4个1byte的数据,也可能存储了2个2byte的数据……,所以CPU在逻辑上将内存单元寻址地址边界设置为4的倍数(如:0,4,8,12……),这是数据对齐产生的必要条件之一;另一个原因是程序中使用的数据类型并非都是4的倍数,如:char(1byte),short(2byte),int(4byte)等等。让我们考虑一下一个2byte的的变量在内存单元中排布吧:如果这个变量地址为0或1或2,那么CPU一次内存访问就能够取得你的变量;但如果是3的话,很不幸,CPU还得访问一次内存以取得全部数据。
何时考虑 数据对齐
在程序对性能属性要求严格的情况下,数据对齐是硬件平台需要考虑的问题,它能提高CPU内存的访问速度。现在的大多数编译器会默认对齐程序中用到的数据,所以程序员一般不需要考虑这些问题。但编译器的擅作主张也未必都是一件好事,譬如网络程序为减少通讯的数据量而传输未经对齐的数据,这时对于接收端就不应该做数据的对齐(下面将要举例),这一点需要格外注意。
举个例子
这个例子是VC6.0下数据对齐问题中的一个:
typedef struct _ipoptionhdr
{
unsigned char code; // Option type
unsigned char len; // Length of option hdr
unsigned char ptr; // Offset into options
unsigned long addr[9]; // List of IP addrs
} IpOptionHeader;

// 用于观察4byte类型变量的每个位
struct type_view
{
unsigned char b1_;
unsigned char b2_;
unsigned char b3_;
unsigned char b4_;
} ;

// 数据流
unsigned char buf_[] = "123456789";

type_view *type_view_;
IpOptionHeader *p_ = (IpOptionHeader *)buf_;
type_view_ = (type_view *)&p_->addr[0];
printf("%c, %c, %c, %c",
type_view_->b1_, type_view_->b2_,
type_view_->b3_, type_view_->b4_);

// 输出结果
// 5,6,7,8
其他编译器如果没有数据对齐调整不会出现以上问题,解决如下:
// 强制数据对齐为1
#pragma pack(1)
typedef struct _ipoptionhdr
{
unsigned char code; // Option type
unsigned char len; // Length of option hdr
unsigned char ptr; // Offset into options
unsigned long addr[9]; // List of IP addrs
} IpOptionHeader;
#pragma pack()

//输出结果为:
// 4,5,6,7
这个例子示例是获取IP路由时用IP选项的数据结构解码串行数据时遇到的数据对齐问题,如果编译器对该数据结构作了对齐处理,那么无论如何都得不到正确的IP地址。
8位CPU 当然不会产生数据对齐问题,当CPU发展到16,32位时,因为CPU的一次内存访问就能取回4个byte(且用32位举例,这个数据理所当然的缓存在相应的32位寄存器中)——里面可能存储了4个1byte的数据,也可能存储了2个2byte的数据……,所以CPU在逻辑上将内存单元寻址地址边界设置为4的倍数(如:0,4,8,12……),这是数据对齐产生的必要条件之一;另一个原因是程序中使用的数据类型并非都是4的倍数,如:char(1byte),short(2byte),int(4byte)等等。让我们考虑一下一个2byte的的变量在内存单元中排布吧:如果这个变量地址为0或1或2,那么CPU一次内存访问就能够取得你的变量;但如果是3的话,很不幸,CPU还得访问一次内存以取得全部数据。
何时考虑 数据对齐
在程序对性能属性要求严格的情况下,数据对齐是硬件平台需要考虑的问题,它能提高CPU内存的访问速度。现在的大多数编译器会默认对齐程序中用到的数据,所以程序员一般不需要考虑这些问题。但编译器的擅作主张也未必都是一件好事,譬如网络程序为减少通讯的数据量而传输未经对齐的数据,这时对于接收端就不应该做数据的对齐(下面将要举例),这一点需要格外注意。
举个例子
这个例子是VC6.0下数据对齐问题中的一个:
typedef struct _ipoptionhdr























type_view_->b1_, type_view_->b2_,
type_view_->b3_, type_view_->b4_);



其他编译器如果没有数据对齐调整不会出现以上问题,解决如下:













这个例子示例是获取IP路由时用IP选项的数据结构解码串行数据时遇到的数据对齐问题,如果编译器对该数据结构作了对齐处理,那么无论如何都得不到正确的IP地址。