所谓字节序,意味着是和字节的顺序有关,一个字节有8bit。
我在这里说的就是字节序和8bit.
所谓字节序,意味着是和字节的顺序有关,一个字节有8bit。
我在这里说的就是字节序和8bit.
一直以为自己了解什么是字节序,当然,是自以为是的了解,今天加班写程序,受了老板(他是一个高手)的点拨,算是了解字节序了吧,希望这次是真的了解了。
说说通用计算机:
操作的最小单位是8bit,也就是说最小的计算单元只能是一个字节的大小。某些特殊的计算机的体系结构可以直接操作1bit的最小单位,但是通用计算机不行。
说说网络字节序:
从网络上传送的数据包也都是以一个一个的字节传送的(我指的不是物理层的概念,物理层来看还是一个bit一个bit的发),举例有三个字节的数据0xABCDEF.它在内存里假设是表示一个16位的整数和一个字符。
也就是说0xABCD是一个16位的整数,0xEF是一个字符(8bit)。
在计算机中,存储介质存储整数0xABCD像下面的方式则称为大端字节序(big ending): ---------------------------------------------------- |
|
| 低地址方向 | 0xAB | 0xCD | 高地址方向 |
|
|
---------------------------------------------------- 如果这个整数是按相反的地址方向存储的话,如下图所示,则称为小端字节序(small ending): ----------------------------------------------------
|
|
|
高地址方向 | 0xAB | 0xCD | 低地址方向
|
|
|
---------------------------------------------------- 不同的计算机体系,会采用不同的字节序。 在网络传输中的字节序处理是大端的字节序,对于可移植的代码来说,把接收的网络数据应该转换成本机的字节序是必须的,一般会有成对的函数用于把网络数据转换成相应的机器字节序或反之。(如果机器的字节序和网络字节序是一样的,通常就把函数定义成空宏)。 我们再看上面这个数据0xABCDEF,由网络上接收后,应该转换成机器字节序,我们假设机器是小端的(大端的则不用转换),那么,在机器内存上可能看起来是这样的,C001-003表示内存地址。 C003 C002 C001
---------------------------------
|
|
| |
| 0xAB | 0xCD | 0xEF |
|
|
| |
--------------------------------- 先分析整数0xABCD,如果要把它转换成机器的小端字节序,那么就变成了: C003 C002
----------------------
|
|
|
| 0xCD | 0xAB |
|
|
|
---------------------- 而字符0xEF则不变: C001 -----------
|
|
| 0xEF |
|
|
----------- 那么这样,我们容易的看出,在大小端字节序转换时,有一个长度的问题,比如说,如果我们要转换的数据是24bit的话,而不是上面的一个整数和一个字符,那么就应该转换成如下的图: C003 C002 C001
---------------------------------
|
|
| |
| 0xEF | 0xCD | 0xAB |
|
|
| |
--------------------------------- 所以,在使用系统提供的字节序转换函数时,一定要清楚地知道要转换的数据的长度,比如说在UNIX/Linux上的(通用x86机) uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort); 函数,但是我们可以看到,系统提供的函数是32bit和16bit的,但是如果我要转换的是一个字符,或是小于一个字符的几个bit的数据呢?(完全可能,像IP包的首部长度就只有4bit) 答案是不必转换,因为在机器存储和网络发送的一个字符内部的bit位存储顺序是一致的,正如我们在上面讲的,不必去转换。
==========END-------------
|