一、大端与小端的名字由来
在乔纳森·斯威夫特的著名讽刺小说《格列夫游记》中,小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。斯威夫特借以讽刺英国的政党之争,在计算机工业中指数据储存顺序的分歧。(ps:名字由来真草率!)
二、概念
大端模式(big endian):数据的高位字节保存在内存的低地址中,而低位字节保存在内存的高地址中。
小端模式(little endian):数据的高位字节保存在内存的高地址中,而低位字节保存在内存的低地址中。
注:高位字节和低位字节其实和我们平时所用的十进制数的个十百千万类似,例如3521,则3在最高位(千位),其次是5(百位),接着是2(十位),最后是1(各位)。
什么,还不明白?
举个栗子:
0x12345678在两种不同字节序的cpu中的存储顺序如下图所示:
假设低地址到高地址方向为从左到右(其实也可能是从下到上、从上到下......这里只是为了说明问题),则
大端(big endian)存储情况为:
小端(little endian)存储情况为:
那么问题来了,如何测试你的机器是大端还是小端?
我们可以依照两种字节序的存储特性来判断,代码如下:
#include<stdio.h>
int main()
{
int x =1;
if(*(char *)&x == 1) //取x的地址,强转为单字节char后解引用
printf(It's little endian!\n); //小端模式
else
printf("It's big endian!\n"); //大端模式
return 0;
}
其主要原理是获取 x 的最低字节,为0x00,说明是大端;为0x01,说明是小端。
更形象的图解如下:
若是大端,则整形数字1应该这样存储:
若是小端,则整形数字1应该这样存储:
可见,我们只需取出最低位的一个字节进行判断就可以看出是大端还是小端了,是不是so easy?
三、不得不提的网络字节序
网络字节序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确地解释。
形象表示如下图所示:
那么问题又来了,网络协议采用的是大端还是小端呢?
所有的网络协议都是采用大端(big endian)方式来传输数据的,因此,有时也将big endian方式称为网络字节序。
几个有用的转换函数:
- htons:将unsigned short类型从主机字节序转换到网络字节序。
- htonl:将unsigned long类型从主机字节序转换到网络字节序。
- ntohs:将unsigned short类型从网络字节序转换到主机字节序。
- ntohl:将unsigned long类型从网络字节序转换到主机字节序。
注:在使用little endiand的机器中,这些函数会按照对应的规则进行转换;在使用big endian的机器中,这些函数会成为空宏。
------------------------------------------------The end------------------------------------------------------