大小端的问题,指的是字长大于8bit的处理器,在处理一个字的时候,将其拆分成多个字节的表示方法。对于大端处理器,高位在低地址,低位在高地址。如0x12345678,在内存中这样表示:
地址 00 01 02 03
数据 12 34 56 78
一般,ARM/MIPS/PPC都是大端处理器。
而对于小端处理器,低位在低地址,高位在高地址。0x12345678这样排列:
地址 00 01 02 03
数据 78 56 34 12
x86属于小端。
这两种排列方法没有好坏之分,但是,对于不同体系结构的处理器之间通讯的时候,有可能产生问题。如MIPS机器发送0x12345678,到了x86接收的时候,就成了0x78563412。
试想,如果通讯中发生这种错误,多可怕啊——
“呼叫021,呼叫021”
那边,120收到了:“收到呼叫,收到呼叫”
“炮轰3309地区!”
“明白,炮火覆盖9033地区”~
于是,无数我方战士被自己人的炮火……
因此,人们制定了网络字节序——和大端字节序一致,高字节先发,低字节后发。这样,对于x86和MIPS/ARM/PPC处理器,对数据的处理流程就不一样了。x86需要将收到的数据按字节序颠倒以后处理,而MIPS/ARM/PPC可以直接处理。编写程序的工程师们为了让代码可移植,定义了以下的宏:
htonl /× 主机序转网络序,long int类型 ×/
ntohl /× 网络序转主机序,long int类型 ×/
htons /× 主机序转网络序,short int类型 ×/
ntohs /× 网络序转主机序,short int类型 ×/
对于小端处理器,这个宏返回颠倒字节序后的值,而对于大端处理器什么都不做。
这些宏如何实现的呢?感兴趣的同学可以去查看Linux或FreeBSD中的源代码。 |