关于四字节对齐的问题

大家可以将下面的程序copy到vc6.0中编译运行下,看看最终 A 与 B变量的内存比较结果是否相同?

可能大部分人的结果都是相同的。

typedef struct tagChipReg
{
 unsigned char a;
 unsigned short b;
}CHIP_REG;

CHIP_REG A,B;

extern void swap(char &a,char &b);

int main(int argc, char* argv[])
{   

 int iCmpRslt = 1;

 A.a = 1;
 A.b = 2;

 B.a = 1;
 B.b = 2;

}

 

但是笔者这里要提醒下,其实这个代码是不安全的:比较结果未必每次都相同。

为什么?

要回答这个问题就不得不说说字节对齐的问题了。

在嵌入式软件领域中,程序员要想写好程序,就不得不知道写硬件相关的知识,否则写出来的程序可能今天、明天运行的结果是对的,但是后天就不一定了。

本例中,我们要知道程序在运行时的状态,在编译器完成编译的时候,会根据CPU访问内存的取值方式不同,产生不同的汇编代码。大多数CPU取值是四字节对齐取值的,这样才会有较高的存储效率,因为现在大多数的CPU是32位的数据线宽度。所以编译器为了产生更高效的代码,多会讲结构体类的数据按照四字节对齐的方式存放到内存。于是上例中的结构体在内存中实际上就是按照下面的形式来存储的:

地址0:/    a         /

地址1:/无效值    /

地址2:/b的高8位/

地址3:/b的低8位/

可见有个地址1中存在一个不确定的值。正是由于这个值的存在,才会导致上例中memcmp的结果存在不确定性。

那么如何解决这个问题?

把这个不确定的值拿掉不就行了吗?答案是肯定的。我们可以通过将结构体强制1字节对齐就可以有效避免这个问题了,但是这个办法在CPU需要大量访问A、B的情况下变得效率低下。更好的办法是判断两个结构体变量是否相同,只判断其每个成员是否完全相同,而不是用memcmp。

大家觉得如何?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值