大端字节序与小端字节序的电脑 对于相同数据的读写产生的分歧以及解决方式

来源:互联网 发布:淘宝卖家群干什么用 编辑:程序博客网 时间:2024/04/29 05:34

这是在国外网站上看到的一篇旧文,对电脑的大端字节序和小端字节序进行了解释和对比;生动详细,层层递进地介绍了这些不同类型字节序的电脑对于相同内存数据的存储,读取,交流等不同的处理方式,及其产生的分歧和解决办法。对于笔者理解电脑内存数据有很大帮助,所以翻译了一下,同时加入了一些笔者自己的理解!以下正文:


开篇:


跟人类说不同的语言一样,电脑用不同的方式存储和理解数据:例如有的从左向右读写数据,有的则反过来;

 

因此如何使电脑间的数据进行正确交流,如何避免数据读、写的分歧,是我们要解决的问题;

 

解决办法:1.使用共通格式,例如网络通讯数据遵循同一个格式:网络字节序

                    2.包含一个“标志头”,描述文件数据格式

 

数据(Data)和数值(Number):


数据(data),在电脑中即是一串串的0、1组成的位或者字节,数据本身没有固有意义,可以被理解为不同的抽象概念,例如“10”可以被理解为数字(number 10):10(十进制),或者数字(number 2):2(二进制),或者其他……

数值(number),具有抽象概念,10就是10,尽管可能有的电脑叫“10”,有的叫“a”,有的叫“1010”

 

数据和数值在电脑中的关系,可以类比于字母组合和单词在人类中的关系。字母组合“like”(类比于数据),英国人(电脑a)理解为“喜欢”(类比于数字),中国人(电脑b)理解为“立刻”(类比于数字);同一个概念“十” (类比于数字),英国人(电脑a)存储为“ten” (类比于数据),中国人(电脑b)存储为“十”,日本人(电脑c)存储为“じゅう”

 

类似于人,电脑也讲不同语言,不同电脑会将同一个数据data理解为不同的数值number,或者将同一个数值number存储为不同的数据data!

 

基本数据格式:

 

电脑将数字存储为数据,就好像人类将一个个实际概念存储为一个个单词。那要是每台电脑都各自为政,还如何交换数据??

 

好在,大多数电脑遵循基本的数据格式,让我们有了个好的起点:

  •   位有两个值(0或者1)
  •   字节有八位:
    • 最左位的值权重最大,例如“00001010”是十进制数字“十”
    • 位0是指最右边位,位7指最左边位

 

这些基本规则成为数据交换的基石。

 

数据交换问题:同一串数据,不同的数值!

 

字节byte在所有机器上都一样,如果我们需要交换的数据是单字节的数据,例如ASCII,那么这些基本的规则已经足够。问题出现在多字节数据的交换上!让我们来看一个完整的例子:

 

同一片内存区:

例如一个四字节的系列数据。现在电脑上有四个byte,命名为W,X,Y,Z,以及他们的地址和对应值如下表:

 

对指针的理解:

在考虑问题之前,让我们先了解一下一个重要概念:指针,尤其对于C编程语言。指针存储的是内存地址,它让我们的程序从内存数据中得到数值,又可以将数值写入到内存数据中。简单说来就是联系起了数据和数值!


单字节指针不会有分歧:

在C中,例如编写如下代码:

void *p = 0; // p指向location 0,但是不确定数据类型,即p不知道//该如何解释这个内存的内容

char *c;    //指向char类型数据,一般是单字节

c = (char *)p; //告诉p将其所指视为char类型,并使c指向了和p//样的地址location 0,即Wcp都会将W值理解//char类型

此时c和p指针均指向单字节,那么它们遍历任何电脑的相同内存数据,都不会有任何分歧,因为单字节的基本规则是统一的(多年之前的情况又不一样欧)。

问题来了!

单字节只能有256的值,0-255。对于长整型数据或浮点数据等不够用呀,因此它们存储为多字节数据。对于多字节数据,电脑就有了不同处理方式:

在大端字节序机器(Bigendian machine)上:先存储大端字节(高位字节),查询时,第一个字节(存在最小地址上)是最高位字节;

在小端字节序机器(Bigendian machine)上:相反,第一字节序是最低位的。

 

多字节指针对数据解读的分歧:

现在有大端字节序电脑a,和小端字节序电脑b,W,X,Y,Z地址和存储数值均如上,也就是说内存区是完全一样的,如果用char类型(单字节)指针c或者p去解释这个内存区,ab不会有任何分歧,但是对于同样的一片内存区,多字节的解读却发生分歧:

short *s; // 指向short int (2 bytes)类型

s = 0;    // 指向location 0; *s s所指的数值

根据大端小端的解释,在a(big…)中,W是高位字节,X是低位字节,故s所指向的值被理解为0x1234;而在b看来,X是高位字节,W是低位字节,故用s读出来的数据却是0x3412,这就是传说中的“NUXI”问题,大端看来是“UNIX”,小端看来是“NUXI”!

 

“大小对话”:

 

电脑之间总是要进行数据交换的,不能闭关锁国,自己说自己的语言,也要懂些外语!

 

方式1:最好的解决方式就是统一字节序,例如网络字节序就是用于网络数据交流的统一格式。标准网络字节序其实就是大端字节序,但是小端爱好者可能会赌气哎,所以嘘!还是叫它网络字节序好了。

将数据传到网络上之前,先转换为网络字节序,电脑会调用函数hton(host-to-network),大端机其实啥也没干(我们都知道但是不说……),但是即使大端机,也最好程序前加上hton使程序具有通用性。

同样还有函数ntoh(network to host),不多解释了。

这些函数在底层网络通讯非常关键,例如ip数据包等

 

方式2:使用字节序标志Byte Order Mark (BOM)。有个神奇的标志数例如0xFEFF,放在每个数据之前,如果有天读起来是0xFEFF,说明这个数据的字节序和本身电脑一样,如果是0xFFFE,反过来了,那就需要翻译一下了。

用这种方式的话,即使只需要送两字节数据,都还要再加上这两字节的标志位,有些伤脑筋吧!

Unicode(统一码)就使用BOM来存储多字节数据,XML避免了这一麻烦,因为它默认使用UTF-8存储数据,将Unicode数据看做单字节数据,单字节数据就没有以上困扰!

 

为什么不能统一字节序?


每个字节序都有其优点,大端比较符合人们理解,数据“左高位右低位”;小端,第一个取出数据就能判断奇偶,可以满足这种特殊需求等。

 

结语:


内存里存储的只是数据,如何认识和解读这些数据,使其变成对于人类具有意义的某些概念和含义才是问题所在。



原创粉丝点击