一、大端字节序和小端字节序
大端字节序:一个整数的高位字节(23~31bit)存储在内存的低地址处,低位字节(0~7bit)存储在内存的高地址处。
小端字节序:一个整数的高位字节(23~31bit)存储在内存的高地址处,低位字节(0~7bit)存储在内存的低地址处。
现代PC大多采用小端字节序,因此其又被称为主机字节序。
对应的,大端字节序也称为网络字节序。
二、字节序的转换
/* 主机字节序到网络字节序的转换 */ unsigned long int htonl(unsigned long int hostLong); unsigned short int htons(unsigned short int hostShort); /* 网络字节序到主机字节序的转换 */ unsigned long int ntohl(unsigned long int netLong); unsigned short int ntohs(unsigned short int netShort);
补:长整型函数通常用来转换IP地址,短整型函数用来转换端口号。
任何格式化的数据通过网络传输时,都应该使用这些函数来转换字节序。
三、余音绕梁
1. 为何网络字节序是大端字节序?
当格式化的数据在两台使用不同字节序的主机之间直接传递时,接收端必然错误地解释之。
提出的解决方法是:发送端总是把发送的数据转化成大端字节序数据(小端机转换,大端机不转换)后再发送,于是接收端知道对方传送过来的数据总是采用大端字节序,所以接收端可以根据自身采用的字节序决定是否对接收到的数据进行转换(小端机转换,大端机不转换)。因此大端字节序也称为网络字节序。
2. 即使你的主机是大端机,最好也在收发数据时进行字节序转换
- 这样写出来的代码可移植性更好
- 这种情况下,字节序转换函数并不会修改数据的字节序
3. 确定主机是大端机还是小端机
void judge() { union { short s; char c[sizeof(short)]; } un; un.s = 0x0102; // 短整数s的高位字节0x01放在内存的低地址处 if(un.c[0] == 1 && un.c[1] == 2) printf("big endian "); // 短整数s的高位字节0x01放在内存的高地址处 else if(un.c[0] == 2 && un.c[1] == 1) printf("little endian "); else printf("unknown... "); }