在解释什么是字节序之前,有必要说一下什么是位(bit),字节(Byte)
位:在计算机中,由于只有逻辑0和逻辑1的存在,例如: 1001 0000 1101等等。其中每一个逻辑0或者1便是一个位。例如这个例子里的1000 1110共有八个位,它的英文名字叫(bit)。
字节:字节是由八个位组成的一个单元,也就是8个bit组成1个Byte。字节有什么用呢? 在计算机科学中,用于表示ASCII字符,便是运用字节来记录表示字母和一些符号~例如字符A便用 “0100 0001”来表示。
计算机能够存储的最小数据单位是字节(Byte);
计算机最小的数据传输单位是bit(比特位);
常见的:int型占4个字节,float型占4个字节, short占2个字节,char是1字节
字节序:cpu对内存中数据(以字节为单位)进行存取的顺序。
大端字节序(big-endian):按照内存的增长方向,高位数据存储于低位内存中。
小端字节序(little-endian):按照内存的增长方向,低位数据存储于高位内存中。
记忆:正常人类读取的顺序为大端,即16进制的0x123456读取顺序为从1开始,依此从左往右读取。因此最先读的是这个数的最高位,但是在内存中该位置的地址最小。
举个例子:
| 内存地址 : 小地址 ————> 大地址 | ||||
|---|---|---|---|---|
| 内存地址 | 0x10 | 0x11 | 0x12 | 0x13 |
| 大端 | 12 | 34 | 56 | 78 |
| 小端 | 78 | 56 | 34 | 12 |
这里也许有人会问,为什么小端不是87654321这样的顺序,这是因为78,56,34,12,共4个块,每一块都属于一个字节,字节是无法颠倒的,因为一个字节表示一个整体,例如我们上面所说的字符A,它的ASCII是97,转换成二进制是“0100 0001”。内部的位顺序是固定的,无论是在大端还是小端。
如上表所示,假设我们的0x12345678的存储起始位置的内存地址是0x10,那么它将会被存在0x10,0x11、0x12和0x13位置上,因为0x12345678每两位(这里的位和上面所说的位不一样,就是字面上位的意思)属于一个字节。那为什么偏偏是两位表示一个字节呢,举一个例子大家获取就明白了,0xff表示二进制"1111 1111",十进制是255。这也是一个字节所能表示的最大值,刚好是两位(f和f)。
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用大端字节序(big endian)。为了进行转换 bsd socket提供了转换的函数 有下面四个:
//htonl 把unsigned long类型从主机序转换到网络序 uint32_t htonl(uint32_t hostlong); //htons 把unsigned short类型从主机序转换到网络序 uint16_t htons(uint16_t hostshort); //ntohl 把unsigned long类型从网络序转换到主机序 uint32_t ntohl(uint32_t netlong); //ntohs 把unsigned short类型从网络序转换到主机序 uint16_t ntohs(uint16_t netshort);
记忆:h是主机host,n是网络net,l是长整型long,s是短整型short。
#includeint main(){ unsigned long a = 0x12345678; unsigned char *p = (unsigned char *)(&a); printf("主机字节序:%0x %0x %0x %0xn", p[0], p[1], p[2], p[3]); unsigned long b = htonl(a); //将主机字节序转化成了网络字节序 p = (unsigned char *)(&b); printf("网络字节序:%0x %0x %0x %0xn", p[0], p[1], p[2], p[3]); return 0; }
运行结果
主机字节序:78 56 34 12
网络字节序:12 34 56 78
思考一个问题:统一使用大端字节序,不是更方便吗,为什么要存在大端字节序和小端字节序?
原因是:计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。
但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。
计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读第一个字节,再读第二个字节。如果是大端字节序,先读到的就是高位字节,后读到的就是低位字节。小端字节序正好相反。



