前言
- 字节序,就是字节的存储顺序。
- 而字节是内存中可寻址的最小单位。
- 8位为一个字节。
- 所有的信息都是由若干个字节组成的
- 那么现在的问题就是,对于十六进制数字0x1234,在内存中是如何存储的?
- 0x1234有2个字节,那么他在内存中有两种存储方式,或者说他有两种表示方式,一种是1234, 一种是3412,注意从左往右,地址从低到高,前者就是大端字节顺序(高位先存储),后者就是小端字节顺序(低位先存储)。
为什么要区分大端和小端?
首先,二者没有优劣,仅仅是不同的方案,就跟你剥鸡蛋壳的时候,从大端打开还是从小端打开一样,都是可以的。贴一下《深入理解计算机系统》中的段子。
其次,当不同的主机进行通信的时候,以大端方式存储的信息,如果以小端方式进行解析,那显然会出错。所以需要区分。已有一些转换函数,暂时不去研究。
如何确定本机是大端还是小端?
大端小端可以认为是操作系统决定的。不同的操作系统的模式是不一样的,例如安卓和IOS都是小端,那么我的64位Intel处理器的Windows是什么模式呢?
下面来研究一下,在这个过程中可以加深我们对指针、字节、强制转换等知识的理解。
思路
- 首先确定一个我们已知的数字,例如0x12345678,用int x 来存储。
- 由于我们希望按照字节顺序地打印x在内存中的值,所以我们用一个char* 的指针来指向这个这个x,然后,就可以用这个char * 类型的指针来按序访问字节了。
代码
网上提供的通常是C语言版本,在此特地使用C++语言,同时故意使用reinterpret_cast强制转换,(虽然他看起来比较冗长),他的作用是显式地告诉编译器,我们希望将int型的指针当成char型的指针,这样他的步长就变成了1个字节,而不是4个字节。
#include<iostream>
using namespace std;
int main(){
unsigned int x = 0x12345678;
unsigned char* p = reinterpret_cast<unsigned char*>(&x); //用char类型的指针指向x
for(size_t i=0; i<4; i++){// x有4个字节
// 将得到的一个字节的数强制转换成整数,再以十六进制输出
cout << hex << static_cast<unsigned int>(p[i]);
}
cout << endl;
}
输出结果
显然,这说明我的机器是以小端字节顺序来存储整数0x12345678的。
补充:程序中示意的x不含有00,因为00的话cout会有问题,这不属于本次讨论范畴。有时间再整理下C++的格式化输出。