计算机字节序是指多字节数据类型在内存中存储顺序的规定。在计算机中,一个多位数据类型的数值在存储器中不是按照它们在数据中的顺序顺序存储的,这是由于计算机用的是二进制,要转成10进制储存亿需要一段特定的顺序,于是就有``大端序''和``小端序''之分。在现代计算机系统中,大多数采用小端序,大端序一般只在某些特定的场合或旧的系统中使用。
一、什么是大端序和小端序
1.1 大端序
大端序,也称为网络字节序(big-endian),是指高位字节在前,低位字节在后,字节序列00000001的存储就是0x01 0x00 0x00 0x00。在网络通信中,经常采用大端序来表示数值。
1.2 小端序
小端序,也称为主机字节序(little-endian),是指低位字节在前,高位字节在后,字节序列00000001的存储就是0x00 0x00 0x00 0x01。在个人计算机等主机上面,几乎全部采用小端序来表示数值。
二、为什么有大端序与小端序
2.1 历史原因
早期计算机结构使用大端序是因为当时计算机内存比较昂贵,程序员更多使用机器码进行开发,并口缘自然需要注意字节顺序。不过后来随着内存变得越来越便宜,计算机操作系统与库函数的普及,大多数软件开发者都脱离了最底层的帮助,从而也就没有意识到大端序的存在。
2.2 性能优化
小端序的存储方式会使内存对齐变得更加方便,在运算时可以将数据按照字节粒度进行处理,可以提高效率。
三、程序员必须关注字节序
3.1 不同操作系统处理字节序不同
不同的操作系统对于字节序的处理可能是不同的。在Windows操作系统上,大多数体系结构默认使用小端序,而在Unix和Linux系统中,由于没有默认字节序,程序员需要手动处理字节序。
3.2 网络通信需要注意字节序
在网络通信时,数据包的字节序必须统一,否则通信会出现问题。在网络通信中,数据字节序采用常见的网络字节序或者大端序。
四、字节序转换
4.1 hton、ntoh
在程序中,可以使用htons、htonl、ntohs、ntohl等标准C库函数来进行字节序转换,这些函数包含在头文件
```c
uint16_t htons(uint16_t hostshort);
uint32_t htonl(uint32_t hostlong);
uint16_t ntohs(uint16_t netshort);
uint32_t ntohl(uint32_t netlong);
```
其中,htons()用于将16位的主机字节顺序转换成网络字节顺序,ntohs()用于将16位的网络字节顺序转换成主机字节顺序。htons()用于将32位的主机字节顺序转换成网络字节顺序,ntohl()用于将32位的网络字节顺序转换成主机字节顺序。
4.2 手动转换
也可以自己编写字节序转换的函数,如下面的代码示例:
```c
void swap(char *a, char *b) {
char temp = *a;
*a = *b;
*b = temp;
}
uint16_t little_endian_to_system(uint16_t little_endian) {
char* little_endian_ptr = (char*)&little_endian;
swap(little_endian_ptr, little_endian_ptr+1);
return little_endian;
}
uint16_t system_to_little_endian(uint16_t system) {
return little_endian_to_system(system);
}
uint16_t big_endian_to_system(uint16_t big_endian) {
char* big_endian_ptr = (char*)&big_endian;
swap(big_endian_ptr, big_endian_ptr+3);
swap(big_endian_ptr+1, big_endian_ptr+2);
return big_endian;
}
uint16_t system_to_big_endian(uint16_t system) {
return big_endian_to_system(system);
}
```
这里写了4个函数,分别把小端序和大端序转换成主机序,以及把主机序转换成小端序和大端序。
五、总结
字节序是计算机系统中一个比较基础的概念,而大端序和小端序的不同之处经常会在一些特殊和底层的场合上涉及。在一般的应用程序中,我们可以使用系统提供的函数,或者自己写函数来完成字节序的转换,从而避免字节序带来的问题。虽然大端和小端的细节并不常见,但作为程序员,必须要对这一点进行了解和掌握。
扫码领取最新备考资料