字节序,顾名思义就是字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据就无需谈顺序的问题),大部分人在实际的开发中很少会直接和字节序打交道。唯有在跨平台以及网络程序中才是一个应该被考虑的问题。
字节序分为两类
- 大端字节序 Big-Endian
- 小端字节序 Little-Endian
Little-Endian 就是低位字节放在内存的低地址端,高位字节排放在内存的高地址端。 Big-Endian 就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
高地址、低地址:内存的空间布局情况中,栈顶总是对应高地址,栈底总是对应低地址。
高位、低位:假设一个32位无符号整型 0x12345678,十进制中靠左边的是高位,靠右边的是低位,在其他进制也是如此。拿 0x12345678 来说,从高位到低位的字节依次是0x12,0x34,0x56,0x78。
我们以表格形式来表现 0x12345678 以不同方式在内存中存储的结构:
| Big-Endian: 低地址存放高位 | Little-Endian: 低地址存放低位 |
|---|---|
| 栈顶 高地址 | 栈顶 高地址 |
| 0x78 | 0x12 |
| 0x56 | 0x34 |
| 0x34 | 0x56 |
| 0x12 | 0x78 |
| 栈底 低地址 | 栈底 低地址 |
由于只能从栈顶出栈、入栈,所以大端字节序存储形式可以看作:0x78563412,小端字节序存储形式是:0x12345678。
网络字节序:4个字节的32 bit 值以下面的次序传输:首先是0-7bit,其次是8-15bit,然后是16-23bit,最后是24-31bit。这种传输次序称作大端字节序。TCP/IP首部中的所有二进制整数在网络传输中都要求以这种次序,因为它又称作网络字节序。
既然网络字节序是大端字节序,那为什么会有小端字节序?而不是统一成大端字节序?
计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理大多都是小端字节序。
但是人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。
计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道顺序读区字节,先读第一个字节,再读第二个字节。
所以在网络编程中,需要调用函数来进行转换。
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到 htons(), ntohl(), ntohs(),htons() 这4个函数。h 代表 host,n 代表 network,s 代表 short,l 代表 long。
- htonl:Host to Network Long,把unsigned long类型从主机序转换到网络序
- ntohl:Network to Host Long,把unsigned long类型从网络序转换到主机序
- htons:Host to Network Short,将主机的无符号长整形数转换成网络字节顺序
- ntohs:Network to Host Short,把unsigned short类型从网络序转换到主机序



