字节序(Byte Endian)

来源:互联网 发布:mysql 更改用户密码 编辑:程序博客网 时间:2024/05/16 07:51

  字节序,顾名思义,就是字节的顺序。如果一个基本数据类型由多个字节构成,那么这些字节在内存中就有一个存放顺序,这就是字节序。大致可以分成两类:大端字节序(Big Endian)小端字节序(Little Endian)。大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。小端则反过来,是低字节数据存放在低地址处,高字节数据存放在高地址处。因而相应的,大端取高字节数据比较方便(这样理论上从高字节开始的比较操作简单一些),小端取低字节数据比较方便(这样理论上从低字节开始的加法操作简单一些;强制转换,譬如把long转成short,也即取低两个字节也简单一些),算是各有优势吧。大小端是由CPU架构决定的,有的CPU架构是大端,有的CPU架构是小端,还有的比较强悍,大小端都支持,能够切换。


  关于字节序,印象中比较深的就是大学机房上课时老师喜欢考这个。盖因为当时用的都是x86系统,字节序是小端,数据在内存里的存放方式不直观。譬如一个long型变量,值为0x12345678L,用内存查看工具查看时,该变量所在内存处存放的数据却依次是78 56 34 12 (内存查看工具一般使用16进制数显示内存数值,地址自左往右是从低地址到高地址),好像顺序颠倒似的。


  其实,字节序是哪种,内存里数据是如何存放的,并不影响变量的正常使用。像什么算术运算、逻辑运算、位运算,都不会有问题。只有需要把长度为多个字节的变量当做字节流来看的时候才需要考虑。哪些情况需要当做字节流来看呢?常见的像内存查看,网络通讯,文件保存这些,它们都是以单个字节为基本处理单位,如果要查看一个多字节长的变量在内存中的表示,要网络传输该变量,要把这个变量保存到文件,那么就需要规定某种字节变换顺序。

  反过来,转换后的字节流如何判断其字节序是大端还是小端呢?这个基本就是要么约定俗成是某种字节序,要么通过设置相应Flag来做标记。
  • 像内存查看,我们可以通过了解平台信息知道字节序;
  • 像网络通讯,网络协议规定网络字节序(Network Order)是大端。
  • 关于文件保存,一般通过做标记方式。像Windows上的记事本,保存成UTF-16格式时可以指定是“Unicode”还是“Unicode big endian”,它是通过文件头部的BOM(Byte Order Mark),U+FEFF来标记的。如果没有标记,只能谁用谁知道了,要么大端和小端都尝试一遍,看看哪种比较合理。微笑


  字节序本身的内容并不复杂,最主要的还是数据转换处理时要有这个概念(特别是C里面进行指针操作时需要注意,指针能够直接寻址,能够强制转换,实在是功能太强大了),然后记住一些相关的东西。譬如C库里面提供了htonl (host-to-network-long)、htons (host-to-network-short)、ntohl、ntohs这些API来进行主机字节序和网络字节序的转换;Java采用大端字节序,相关的字节变换处理缺省是基于大端之类。

原创粉丝点击