C总结_5(字节序)
-------------------------
测试字节序程序(编译环境VC++6.0)
#include <stdio.h>
int main()
{
}
输出结果
128
结论:Window平台上使用小字写序,即低位存放在低地之内存,高位存放在高地址内存。(UNIX平台上使用大字写序)
-------------------------
一道关于字节序的题目 printf("%d\n", *p); printf("%d\n", *(p+1)); short i = 32768; //2进制10000000,00000000 unsigned char *p = (char *)&i;
计算程序执行完的结果:(编译环境VC++6.0) short a;
char *p;
a = 1234;
p= (char *)&a;
*p = 56;
请问题变量a的数值为( D )。
1234; B) 3456; C)5634; D)1080
解答:
2进制a:00000100,11010010
因为Window平台上使用小字写序,所以p指向11010010。
字节序及其在导航系统造成的混乱
赵兴华
字节序”这个字眼,相信大家都不陌生,搞嵌入式和网络编程的都应该精于此道。但是,有些事情越是熟悉,越是不容易引起人们的注意,正如“最危险的地方,最安全”,最安全的地方,也往往最危险。在我们事业部赫赫有名的中国导航项目中,就存在着一个跟字节序相关的稍稍有点戏剧性的问题。
字节序的概念
对于不同软件和硬件之间的差异,在技术人员看来除了叹息,不会有更多的情绪,这样的现象是多种原因造成的,可是对于人为的差异,我们总还是痛恨不已,字节序就是这样一个列子。简单的说,字节序就是在处理数字时,机器和实际数字高低位顺序,分为大字节序( Big endian )和小字节序( little endian )两种。用 google 搜索可以得到很多相关的文章,其中有一篇:
http://www.princeton.edu/~kazad/resources/cs/endian.htm
讲得比较好,精髓是两句话:
Big endian : It thinks the first byte it reads is the biggest.
Little endian : It thinks the first byte it reads is the least.
读取两个字节或者四个字节时,先从要读取的起始地址开始,——“ the first byte it reads ”, the biggest 就是从起始地址读出来的是最大的,按照人类数学思维习惯,比如 1024 ,数字越在左边的级数就越大,所以这里最大的可以理解为把它摆在左边(呵呵 , 为了符合人类的逻辑)。
举个例子,在内存地址 0x00000000 开始
0x00000000 存放着 0x12
0x00000001 存放着 0x34
0x00000002 存放着 0xab
0x00000003 存放着 0xcd
当我们去读取地址 0x00000000 的内容时,伪码:
int *s;
s = 0; // 指向地址 0x00000000
print”s”;
如果字节序是 big-endian ,因为第一个读到的字节是 0x12 ,所以放在最左边,依次读取,最后读到的内容是 0x1234abcd ;如果字节序是 little-endian ,因为第一个读到的字节是 0x12 ,最小,所以放在最右边,依次读取,最后读到的内容是 0xcdab3412 。
同理,当存储两个字节或者四个字节时,伪码:
int *s;
s = 0; // 指向地址 0x00000000
*s = 0x1234abcd;
按照上边的规则,最后的内存内容是:
big-endian
0x00000000 0x12
0x00000001 0x34
0x00000002 0xab
0x00000003 0xcd
little-endian
0x00000000 0xcd
0x00000001 0xab
0x00000002 0x34
0x00000003 0x12
文章最后有一句话:
It's not really a "problem" unless the big endian machine reads the data in the litte-endian one. Each machine is internally consistent.
导航系统存在的问题
跟分布式系统中的“三层结构”相类似,我们的导航系统也可以分为数据层、应用层和表示层。问题就出在数据层和应用层,情况是这样的:
数据是按照大字节序保存的,而使用数据的平台(导航机)和制作数据的平台( Compaq 主机和 Intel PC 机)都是小字节序的。就是说,制作数据的时候,需要把字节顺序翻一下(小字节序 → 大字节序),导航程序在使用数据的时候需要再翻过来(大字节序 → 小字节序)!除了纠正字节顺序不一致,这些操作没有其他任何意义。
可能的结局
产生这样的问题,可能是由于一些“客观因素”或者“历史原因”,比如原来的导航机是大字节序的,数据为了导航机的需要,也按照大字节序保存;也可能是因为大字节序的数据比较方便调试,等等。我们觉得,理想情况下,数据的字节序应该跟导航机的保持一致。
如果要解决这个问题,可以从性能、工作量和系统稳定性等几个方面权衡考虑。很显然,如果要改善的话,制作数据的程序修改工作量并不大,麻烦的是应用层。现在应用层的各个模块都有一些“字节读取”的函数(比如 Get2bN 、 Get2bD 等),而且程序中可能还有其他地方与此相关,总的来看,改动的地方比较大。但是,如果真的能给性能带来很大的改善的话,在年度改善的时候,也是可以考虑的。
本文的目的,仅仅是让大家清楚这样的一个问题。