可移植的嵌入式编程:注意字节序、字节位宽
0赞
本文谈谈嵌入式cpu的字节序和字节位宽对软件可移植性的影响,假设有A、B两台不相同的计算机之间互相通信。有下列数据结构定义:
union data_pack
{
unsigned long word;
unsigned char bytes[4];
};
在A计算机中,用下列语句:
union data_pack bufA;
bufA.word = 0x12345678;
for(i = 0; i < 4; i++)
{
send_byte(bufA.bytes[i]);
}
把数据发送到B计算机上,B机用下列代码接收:
union data_pack bufB;
for(i = 0; i < 4; i++)
{
bufB.bytes[i] = read_byte( );
}
这样,B机能否正确接收数据呢?答案并不肯定。
如果A机和B机的平台相同的话,B机能够收到正确的数据。
即使A和B机的硬件完全一致,但编译器对存储器大小端设置不一致的话,将有bufB.word=0x78563412。为什么会这样呢?假定A机是小端存储,而B机是大端存储,那么bufA和bufB在A和B中的存储格式如下表:

显然,A机中,0x12出现在word的最高字节位置,在B机中则变成最低字节位置了。
如果说大小端问题还比较常见的话,那么,目标机字节位宽的问题,隐藏得就比较深了。即使双机的大小端设置相同,但双击字节位宽不同的话,bufB.word也不能得到正确的值,如下表所示。

因此,这段程序在不同的硬件体系上运行时,结果可能不是我们所希望的,那这段代码怎样写,才能得到正确的结果呢?下面是一个更安全的代码,无论A机和B机的字节序和字节位宽如何,都可以得到正确的结果,代价是,执行时间会长一些,代码占用的空间也会大一些。
A机代码:
unsigned long word;
unsigned char bytes[4];
word = 0x12345678
bytes[3] = (word>>24) & 0xff;
bytes[2] = (word>>16) & 0xff;
bytes[1] = (word>>8) & 0xff;
bytes[0] = word & 0xff;
for
