关于网络字节序和主机字节序

来源:互联网 发布:unity3d粒子系统喷泉 编辑:程序博客网 时间:2024/06/03 02:27

高位字节,低位字节应该怎么理解

  

一般一个16位(双字节)的数据,比如 FF1A  (16进制)
那么高位字节就是FF,低位是1A

如果是32位的数据,比如  3F68415B
高位字(不是字节)是3F68
低位字是415B

右边是低位,左边是高位


通常我们从最高有效位(most significant digit)开始自左向右书写一个数字。


计算机内存中一个字节的位相当于二进制数的位,这意味着最低有效位表示1,倒数第二个有效位表示2×1或2,倒数第三个有效位表示2×2×1或4,依此类推。如果用内存中的两个字节表示一个16位的数,那么其中的一个字节将存放最低的8位有效位,而另一个字节将存放最高的8位有效位。存放最低的8位有效位的字节被称为最低有效位字节或低位字节,而存放最高的8位有效位的字节被称为最高有效位字节或高位字节。
            高位字节                       低位字节
 ↓-----------------------------↓ ↓-----------------------------------↓           
 
15  14  13  12  11  10  9.  8.  7.  6.  5.  4.  3.  2.  1.  0. 



一个16位的数占两个字节的存储空间,即高位字节和低位字节。如果你是在纸上书写一个16位的数,你总是会把高位字节写在前面,而把低位字节写在后面。然而,当这个数被存储到内存中时,并没有固定的存储顺序。


 什么是字节序?是指整数在内存中保存的顺序。

      字节序有两种:
      a.小端模式---Little endinan 低位存储在内存的低地址高位存储在内存的高地址

     b.大端模式---Big endian     高位存储在内存的低地址低位存储在内存的高地址


Little endinan:    最符合人的思维的字节序。

地址低位存储值的低位,地址高位存储值的高位

怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说

低位值小,就应该放在内存地址小的地方,也即内存地址低位

反之,高位值就应该放在内存地址大的地方,也即内存地址高位

Big endian: 最直观的字节序 
地址低位存储值的高位 ,地址高位存储值的低位 

为什么说直观,不要考虑对应关系 
只需要把内存地址从左到右按照由低到高的顺序写出 
把值按照通常的高位到低位的顺序写出 
两者对照,一个字节一个字节的填充进去 


例子:在内存中双字0x01020304(DWORD)的存储方式 
内存地址 
4000 4001 4002 4003 
LE 04 03 02 01 
BE 01 02 03 04 


网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。


这样就给编写网络程序的程序员带来一个问题,程序员必须把本地数据从主机字节序转换成网络字节序发送到主机,同时,主机也必须把收到的数据从网络字节序转换成本地字节序,这样才能保证双方正确的收发数据。


winapi提供了四个函数用于进行网络字节序到本机字节序和本机字节序到网络字节序的转换:
htons:把unsigned short类型从主机序转换到网络序
htonl:把unsigned long类型从主机序转换到网络序
ntohs:把unsigned short类型从网络序转换到主机序
ntohl:把unsigned long类型从网络序转换到主机序

(s表示short,l表示long,n表示network,h表示host)


char类型是没有字节序的问题的,只有大于一个字节的数据类型才有字节序的问题。


判断是大端还是小端

#include "stdio.h"
int main()
{
  union w
 {
  int a;  //4 bytes
  char b; //1 byte
 } c;
  c.a=1;
  if (c.b==1)
  printf("It is Little_endian!\n");
  else
  printf("It is Big_endian!\n");
  return 1;
}



0 0
原创粉丝点击