本文谈谈嵌入式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机 | B机 | ||
base address +3 | 0x12 | word[31:24] | bytes[3] | word[7:0] | bytes[3] |
base address +2 | 0x34 | word[23:16] | bytes[2] | word[15:8] | bytes[2] |
base address +1 | 0x56 | word[15:8] | bytes[1] | word[23:16] | bytes[1] |
base address | 0x78 | word[7:0] | bytes[0] | word[31:24] | bytes[0] |
显然,A机中,0x12出现在word的最高字节位置,在B机中则变成最低字节位置了。
如果说大小端问题还比较常见的话,那么,目标机字节位宽的问题,隐藏得就比较深了。即使双机的大小端设置相同,但双击字节位宽不同的话,bufB.word也不能得到正确的值,如下表所示。
A机字节宽度 | B机字节宽度 | B机收到的bufB.word值 |
8位 | 8位 | 0x12345678 |
8位 | 16位 | 0x560078 |
16位 | 8位 | 0x340078 |
8位 | 32位 | 0x78 |
32位 | 8位 | 0x78 |
16位 | 32位 | 0x78 |
32位 | 16位 | 0x78 |
因此,这段程序在不同的硬件体系上运行时,结果可能不是我们所希望的,那这段代码怎样写,才能得到正确的结果呢?下面是一个更安全的代码,无论A机和B机的字节序和字节位宽如何,都可以得到正确的结果,代价是,执行时间会长一些,代码占用的空间也会大一些。
A机代码:
unsigned long word;
unsigned char bytes[4];
bytes[3] = (word>>24) & 0xff;
bytes[2] = (word>>16) & 0xff;
bytes[1] = (word>>8) & 0xff;
bytes[0] = word & 0xff;
for