大小端字节序以及网络序和主机序的转换

引言:

字节序的问题:小端表示:最低有效字节放在低地址

                            大端表示:最高有效字节放在低地址

比较容易记住的方法是:假如:int  a = 0x 12345678 ;   对于小端,顺时针旋转, 12

                                                                                                                                             34

                                                                                                                                             56

                                                                                                                                             78

   正好低位放在低地址,假如有如下代码:  char str = *a ; 那么str = 0x 78;

   大端模式,逆时针旋转   AA放在低地址,   char str = *a ; 那么str = 0x 12;

在不同机器间传输数据的时候,需要进行字节序转换,当从网络上取回数据,也需转换字节序。

转换字节序的方法:通过ntohs,ntohl函数将整数进行转换。这个函数的功能是将网络序转换成主机序,在大端机器上它什么也不做

                  htonlhtons用于本机序转换到网络序

               没有对char型字节的转换:

 模拟ntohs,ntohl的实现:

// 短整型大小端互换

#define BigLittleSwap16(A)  ((((uint16)(A) & 0xff00) >> 8) | \

                                                 (((uint16)(A) & 0x00ff) << 8))

 // 长整型大小端互换

#define BigLittleSwap32(A)  ((((uint32)(A) & 0xff000000) >> 24) | \

                                                 (((uint32)(A) & 0x00ff0000) >> 8) | \

                                                 (((uint32)(A) & 0x0000ff00) << 8) | \

                                                 (((uint32)(A) & 0x000000ff) << 24))

假如 定义 short a = 0x 0;  字节序转换后为  0 ;short  a = 0x 1;  0000 0000 0000 0001 转换后为 0000 0001 0000 0000   十进制256

         定义  int     a  = 0x 0;  字节序转换后为 0; int  a = 0x 1;     0000 0000 0000 0000 0000 0000 0000 0001 转换0000 0001 0000 0000 0000 0000 0000 0000 值16777216

 

位域问题:

  但是在C语言中存在一种特殊的数据结构:位域。它的存在,使得C程序员能方便地进行位操作(比如在网络协议中经常出现1bit或者多bit的标示位,它们不是一个完整的字节)。但同时也引起一些难以察觉的问题,这些问题的根源仍然是前面提到的端序。

与字节序一样,一个字节中的8bit顺序在不同端序的机器上并不相同。大端机器上从低地址到高地址顺寻分别是msb->lsb,如下图:

现代计算机的最小存储单位是BYTE,无法对bit寻址,因此我们无法直接观察每个字节内部bit的顺序。但是我们仍然可以通过位域来间接观察字节内部bit顺序,以印证上面的说法

我们看看下面的程序。

#include <stdio.h>
typedef struct OneByte
{
     char bt0 : 1;

     char bt1 : 1;

     char bt2 : 1;

     char bt3 : 1;

     char bt4 : 1;

     char bt5 : 1;

     char bt6 : 1;

     char bt7 : 1;

} ONE_BYTE;

int main()
{
    ONE_BYTE onebyte = {0};

    onebyte.bt7 = 1;

    printf("onebyte = %#x/r/n", *((unsigned char *)&onebyte));

    return 0;

} 
[转]字节序、位序

 

而在VC2005中编译运行的结果如下:

[转]字节序、位序

 

0x80转换成二进制是1000 0000。由于在X86(小端序)中,高地址bit7是msb,因此onebyte的值是0x80了;这就证实了前面的说法。 相应的如果是在大端序计算机中,bit7是lsb,则onebyte的值是0x01

所以位域在大小端机器上要相反定义,例如:

#ifdef BIG_ENDIAN

     char th_x2 : 4;

          th_off: 4;

#else

     char th_off: 4;

          th_x2 : 4;

#endif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值