什么是大小端?
大端:高位数据存放在低地址,低位数据存放在高地址。
小端:高位数据存放在高地址,低位数据存放在低地址。
举个例子,一个 short 类型的数,用十六进制表示出来是 0x1234,那么,0x12就是高位了,0x34就是低位了。然后我们看看数组的地址,一个 byte 数组 buf[2],其中,buf[0] 是地地址,buf[1]是高地址。那么,大端的数据是这样放的 :
buf[0] | 0x12 | 低地址 | 高位数据 |
buf[1] | 0x34 | 高地址 | 低位数据 |
这样子比较符合日常的阅读,类似于读字符串那样子。那么小端的则搞好相反:
buf[0] | 0x34 | 低地址 | 低位数据 |
buf[1] | 0x12 | 高地址 | 高位数据 |
这样子感觉上是将 12 34 倒着存起来。
为啥会有大下端之分呢
这就像鸡蛋应该从小头打碎还是大头打碎一样,没有对错,只是方式不同。
一般情况下,x86架构都是使用的小端模式,而且只支持小端。ARM默认小端模式,但是可以切换为大端。
编译器也会有大小端之分,C语言默认是小端,java是大端。
网络上传输的数据普遍是大端的。
怎么判断机器是大端还是小端呢
在 windows下,使用C#,可以这样判断:
int i = 1;
//将int 转换到数组中,然后根据数组的地址进行判断
byte[] buf = BitConverter.GetBytes(i);
if(buf[0] == 1)
{
Console.WriteLine("小端");
}else{
Console.WriteLine("大端");
}
使用C语言其实更容易判断,通过指针和取址运算:
int i = 1;
//将 int 类型转换为 char*,然后拿到第一个字节的数据进行判断
char c = *(char *)&i;
if (c == 1)
{
printf("小端");
}
else
{
printf("大端");
}