在做通信时,涉及到大端小端!
大端模式和小端模式如何记忆? 转载自:http://blog.chinaunix.net/uid-25906157-id-3164447.html
&lw---------------------------------------->>
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
&lw--------------------------------------->>
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
在小端模式下,应该这样读: 0x78563412
所有计算机处理器都必须在这两种Endian间作出选择。但某些处理器(如MIPS和IA-64)支持两种模式,可由编程者通过软件或硬件设置一种Endian。以下是一个处理器类型与对应的Endian的简表:
· 纯Big Endian: Sun SPARC, Motorola 68000,Java Virtual Machine
· Bi-Endian, 运行Big Endian模式: MIPS运行IRIX, PA-RISC,大多数Power和PowerPC系统
· Bi-Endian, 运行Little Endian模式: MIPS 运行Ultrix,大多数DEC Alpha, IA-64运行Linux
· Little Endian: Intel x86,AMD64,DEC VAX
如何在程序中检测本系统的Endianess?可调用下面的函数来快速验证,如果返回值为1,则为Little Endian;为0则是Big Endian:
- int testendian() {
- int x = 1;
- return *((char *)&x);
- }
Endianness对于网络通信也很重要。试想当Little Endian系统与Big Endian的系统通信时,如果不做适当处理,接收方与发送方对数据的解释将完全不一样。比如对以上C程序段中的变量d,Little Endian发送方发出11 22 33 44四个字节,Big Endian接收方将其转换为数值0x11223344。这与原始的数值大相径庭。
为了解决这个问题,TCP/IP协议规定了专门的"网络字节次序",即无论计算机系统支持何种Endian,在传输数据时,总是数值最高位的字节最先发送。从定义可以看出,网络字节次序其实是对应Big Endian的。
为了避免因为Endianness造成的通信问题,及便于软件开发者编写易于平台移植的程序,特别定义了一些C语言预处理的宏来实现网络字节与主机字节次序之间的相互转换。htons()和htonl()用来将主机字节次序转成网络字节次序,前者应用于16位无符号数,后者应用于32位无符号数。ntohs()和ntohl()实现反方向的转换。这四个宏的原型定义可参考如下(Linux系统中可在netinet/in.h文件里找到):
- #if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
- #define htons(A) (A)
- #define htonl(A) (A)
- #define ntohs(A) (A)
- #define ntohl(A) (A)
- #elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
- #define htons(A) ((((uint16)(A) & 0xff00) >> 8) | (((uint16)(A) & 0x00ff) << 8))
- #define htonl(A) ((((uint32)(A) & 0xff000000) >> 24) | (((uint32)(A) & 0x00ff0000) >> 8) | (((uint32)(A) & 0x0000ff00) << 8) | (((uint32)(A) & 0x000000ff) << 24))
- #define ntohs htons
- #define ntohl htohl
- #else
- #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both."
- #endif