字节序
前言
内存在读写数据的时候,都是以字节为单位进行读写的,其最小的读写单位也是字节。一个字节占8位,如果暂且只考虑无符号数,那么其能表示的范围只有0 ~ 255这256个整数数值。如果将一个字节数据存入内存,那么将很好的对这一个字节的数据进行读写操作。然而,事实上却是,现实生活中的数据往往都是大于一个字节的,例如,在我们现在常用的PC机(32位或64位)中,占用一个字节的数据类型很少很少了,常见的就char,int都需要占用4个字节,double更是占用8个字节。就因为这个原因,对于这个大于一个字节的数据的存储就不得不用多个字节来对其进行存储了,那么现在问题就来了,这些大于一个字节的数据怎么对其进行读写操作的呢?
什么是字节序?
我们现在已经知道了,大于一个字节的数据在内存中的存储肯定也是大于一个字节的,但是呢,正所谓解决了多字节的存储问题,就引入了一个新的问题,那就是,多个字节的数据将怎么对其进行读写操作呢?
由此就引入了字节序这么个东西了。字节序,顾名思义,就是字节顺序。
现在不妨请大家想一想,如果我们这里有一个两字节的整数数据存在了内存当中,我们在对这个两字节的数据进行读取的时候,最大的问题是啥?
这里补充一下,刚提过的,内存数据的读写操作都是以字节为单位的,也就是一个字节一个字节的操作,并且是从内存的低地址向高地址方向的。在读取内存数据时候有两个基本的的操作,一个“随机”的,一个是“线性”的。“随机”的意思就是内存是个随机存储器,也就是我们常说的RAM((Random Access Memory),因此就能跳到内存的任意位置去读取那里的存储数据(这也是为啥我们内存条的访问速度比ROM快很多的一个原因)。“线性”的意思就是,在读取内存数据的时候,就得从随机读取的开始地址处,像一条直线一样的从低地址向高地址读取。
那么我们对这个两字节的数据进行读取的时候,最大的问题就莫过于是:我们当前读取的这个字节是这个两字节数据的高位还是低位呢?
假设,这个两字节的整数数据,其十六进制是:0x1234。我们现在读取到的一个字节是0x12,那么你怎么知道这个0x12是他的高字节还是他的低字节呢,如果这个都搞不清的话,那么在对数据进行读写的时候,肯定也都是错的。
也就是说,数据的低字节应该存在内存的高地址处还是低地址处?由此就出现了字节序,完整的说就是数据的以字节的方式进行存储的时候,其低位在内存中的存储顺序。这就是字节序
大端字节序、小端字节序
由于数据在内存中的存储顺序,就出现了两种顺序,并且是两种完全相反的顺序。
- 1、小端字节序
小端字节序,就是数据存储时,是数值的低字节存储在低地址处,高字节存储在高地址处。如下图:
- 2、大端字节序
大端字节序,就是数据存储时,是数值的低字节存储在高地址处,高字节存储在低地址处。如下图:
P.S. 这里的解释开头就是低字节存储在什么地址,而不是高字节存储在什么地址,方便记忆,因为低和小对应,高和大对应。并且cpu读取内存也总是从低地址开始读取的
其各自优势
- 小端: 在做数据类型强制转换的时候,不需要再对字节进行调整了,因为低位在低地址处
- 大端: 符号位的判断变得方便了,因为高位在低地址处
这里分别解释下其各自优势的原因。
小端: 当在做数据类型强制转换的时候有两种情况,一种是将低精度的向高精度的进行转换,这种转换,大小端字节序存储时都没啥影响,因为都无非是将转换后的高精度的的高位全部填充为零即可。例如,两字节的0x1234要转换为四字节,那么就只需将转换后的高位填零,也就变成了0x00001234。
另一种就是高精度转换为低精度。这种强制数据类型转换必然会导致丢失一部分的精度,那么就得考虑丢弃掉哪部分的精度了。编译器对于这种方式的转换原则是,丢弃掉数值的高字节,只保留下低字节数据。例如,将两字节的数值0x1234强制转换为一字节,转换后的数值就是0x34。
因为其低字节就是存储在低地址处,在做高精度强制类型转换成低精度的时候就不需要再对其进行字节上的调整了,因为我们刚说过,内存数据的读取是“线性”的,也就是低地址挨着读取的位置最近,那么在这种精度转换的时候,就能直接一口气拿到前面的低位数据。那么大端字节序就还得先移位到高地址处才能拿到低位的数据大端: 众所周知,有符号位的时候,符号位都是存储在数据的最高一位的。刚好,大端字节序时,高位就是存储在离读取位置最近的低字节处,那么在获取符号位时就相对方便了很多,不需要再像小端字节序那样移位到高地址去取
结语
从这里可以看出,大小端字节序是各自互斥的,如果你选择了一种字节序,那么就必定要放弃另一种字节序。不同的CPU架构选择了其各自的字节序,小端的典型代表就是我们常见的x86架构的CPU,大端的典型代表就是IBM。如下:
小端字节序: x86(例如:Intel和AMD),DEC
大端字节序: IBM、PowerPC和Sun
ARM体系的CPU更是厉害,他们大小端都用,但是呢,具体ARM选择哪种字节序,这就得由硬件厂商决定了。
当然,字节序不仅仅存在于CPU访问内存时的概念,还包括了现在的文件存储啊,网络传输啊。网络字节序就是选择的大端字节序,bmp格式图片的存储就是选择的小端字节序。具体选择哪种就看其开发者自己咯。
参考书籍:《操作系统真象还原》 -- 郑钢著