我们知道,字节序分为big-endian 和 little-endian ,采用大端的机器有IBM体系结构,相反intel体系结构主机则采用小端。另外我们需要知道的是,在网络编程中,字节序为大端,所以我们要实现主机字节序到网络字节序的转换。这里有一个需要说明的是,为什么网络字节序需要采用大端。主要是大端有一个特点,我们书写某个数的16进制形式(从左至右:高字节->低字节)和内存中存储形式一样的(从左至右:低地址->高地址)是一样的,外观一样,所以网络字节序好理解(个人观点,呵呵),从括号中我们可以知道。
(附:在网络传输中,采用big-endian序,对于0x0A0B0C0D ,传输顺序就是0A 0B 0C 0D(传输的时候从低地址开始) ,因此big-endian作为network byte order,little-endian作为host byte order。为什么X86存储会使用little-endian,起初我想对于位运算,尤其是位移运算,little-endian很方便,但转念一想,big-endian也方便啊,无非是左移和右移的区别而已,但little-endian的优势在于unsigned char/short/int/long类型转换时,存储位置无需改变。如short a = 0x1234;小字节序主机存储内存如下:
add add+1
34, 12
2011-07-22更新)
int b = (int)a 后,b内存存储为:
add add+3
34 , 12 , 00 , 00
可以知道,类型转换非常简单,只在后面添加0x0000即可)
大端字节序即 最重要的字节(高位,也称为the most significance of bytes)存放在低地址(前面的地址,即前面),高位在前,也就是我们书写的形式。
比如:0x12345678 。
如果采用大端,在内存中存放如下:
add add+3
12 , 34 , 56 , 78
和我们书写形式是一样的。
如果采用小端,将存放如下:
add add+3
78 , 56 , 34 , 12
总结如下:大端即高位(字节)在前(低地址),小端即低位(字节)在前(低地址)
有了上面的讨论,本文具体讨论下glibc下面字节序的相关实现机制。本文主要涉及的库文件包括 :
/usr/include/bits/endian.h
/usr/include/endian.h
/usr/include/bits/byteswap.h
/usr/include/byteswap.h
/usr/include/bits/endian.h
/* This file defines `__BYTE_ORDER' for the particular machine. */
该文件主要定义了具体的机器的字节序,如对于Intel i386是小端字节序
1 /* i386 is little-endian. */
2
3 #ifndef _ENDIAN_H
4 # error "Never use <bits/endian.h> directly; include <endian.h> instead."