CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C语言

字节序的问题

楼主tcww88(wuwei)2006-03-15 13:10:02 在 C/C++ / C语言 提问

看了网上流传甚广的一个自己写的ping程序,看到下面的语句,不解:  
  /*校验和算法*/  
  unsigned   short   cal_chksum(unsigned   short   *addr,int   len)  
  {   int   nleft=len;  
  int   sum=0;  
  unsigned   short   *w=addr;  
  unsigned   short   answer=0;  
   
  /*把ICMP报头二进制数据以2字节为单位累加起来*/  
  while(nleft>1)  
  {   sum+=*w++;  
  nleft-=2;  
  }  
  /*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/  
  if(   nleft==1)  
  {   *(unsigned   char   *)(&answer)=*(unsigned   char   *)w;  
  //ok,这里就是不明白的地方,这样我发现只是把最后一个字节放到路一个short型的低位而不是高位,实验证明也是如此,是不是作者错了?????????????????  
  sum+=answer;  
  } 问题点数:20、回复次数:4Top

1 楼duduhaha(三人行必有我师)回复于 2006-03-15 14:03:27 得分 15

应该没错.指针增加是往高地址方向走的.  
   
  看看下面的介绍.  
  LittleEndian&BigEndian  
  这个标题中的Endian是什么意思呢?还是让我们先来看看下面的情况,这是内存中一个WORD值中的内容,那么这个WORD中的值是0x1234呢,还是0x3412   ?      
   
  low   byte   high   byte      
  0x12   0x34      
   
  熟悉x86汇编的人立刻就知道这个值应为0x3412,很对,但在一些情况下,比如说你在SGI的机器上看到这种情况,则正好相反,0x1234才是正确答案,这与CPU内部处理数据的方式有关。这两种处理方式都存在于不同厂商生产的CPU之中,在上例中若此WORD值为0x3412的,我们称之为little-endian,   若为0x1234的,我们称之为big-endian,这是两种不同的byte   orders。MSDN中有比较精确的定义如下:    
   
  Byte   Ordering   Byte   ordering   Meaning      
  big-endian   The   most   significant   byte   is   on   the   left   end   of   a   word.      
  little-endian   The   most   significant   byte   is   on   the   right   end   of   a   word.      
   
  一般来说我们不用关心byte   ordering的问题,但若要涉及跨平台之间的通信和资源共享,则不得不考虑这个问题了。也许你会说,我永远不会去用其它非x86的CPU,也许是这样,你甚至可以不必知道我们最常用的Intel,AMD等生产的x86的byte   ordering是little-endian的,而且按现在的装机数量来看,可以说世界上绝大多数CPU是little-endian的,但多了解一些没有什么坏处,也许有用上的一天,实际若您要涉及到网络编程,了解一些还是有所帮助的,看完本文后您就应该知道为何socket编程中为何要用到如   ntohl,   htonl,   ntohs,   htons这几个看起来名字似乎怪怪的API了,也很容易理解这些函数名的意义了。    
   
  假设我们要在不同byte   ordering的机器之间传输和交换数据,那该怎么办呢,有两个方法,一是全部转换成文本来传输(如XML使用的),另一个方法两方都按照某一方的byte   order,这时就涉及到了不同byte   order之间相互转换的问题(网络传输标准如TCP/IP采用第二种方法并且由于历史的原因,byte   ordering是big-endian的)。两种之间该如何转换呢?方法有很多,我们可以先看看MFC中在处理serialize的代码中所用的方法(List),   虽然代码应该是高效易读的,   但我个人并不喜欢它,   原因是我觉得这不是一种通用优美的方法.下面列出的是我自己写的转换的代码:    
   
   
  template    
  F3D_INLINE   T   ConvertEndian(T     t)    
  {    
  T   tResult   =   0;    
  for   (int     I   =   0;   I   <   sizeof(T);   ++   I)    
  {    
  tResult   <<=   8;    
  tResult   |=   (t   &   0xFF)   ;    
   
  t   >>=   8;    
  }    
   
  return     tResult;    
  }    
   
  原理非常简单,交换字节顺序,我就不多说了,当然这个写法并不是快速的,   只是通用的(我没条件试,   若有不对之处请指出),   若要快速的代码,可以在不同platform上用与platform相关的代码,   如在PowerPC上有   load   word   byte-reversed   indexed   (lwbrx)   和   load   halfword   byte-reversed   indexed   (lhbrx)   指令,   在x86上还可用BSWAP单个汇编指令等,在类型上专为int16,   int32写的通用的代码也可以比这快得多.      
   
  当然如果在byte   ordering相同的情况下,应该不必用这个转换函数,所以我们可以定义一个宏来处理不同的byte   ordering,也可以在运行时测试byte   ordering,   下面的代码给出了一个简单的测试方法。      
   
   
  //   Test   for   endianness.    
  F3D_INLINE   bool   IsLittleEndian(void)    
  {    
  DWORD   dwTestValue   =   0x12345678L;    
  return     (*((BYTE*)&dwTestValue)   ==   0x78);    
  }    
   
  但是float比较怪,有可能所涉及到不仅仅是byte   order的问题,因为有些平台如Alpha不使用IEEE的浮点格式,还得自己转换。当然同上,其它的方法一是将所用的float用文本方式输入输出,另一个办法是在某些情况下可将其转换成定点数再处理,这里我不再深入。    
   
  如果是读写第三方已经指定byte   order的文件或数据流,比如说读SGI的位图文件格式,则可以直接自行按指定的byte   order拼起来,不必考虑host机是何种byte   ordering。下面我给出相应的代码:    
   
   
  //   Read   a   little-endian   TYPE   from   address    
  template    
  F3D_INLINE   T   GetLittleEndian(const   BYTE*     pBuf)    
  {    
  T   tResult   =   0;    
  pBuf   +=   sizeof(T)   -   1;    
  for   (int     I   =   0;   I   <   sizeof(T);   ++   I)    
  {    
  tResult   <<=   8;    
  tResult   |=   *pBuf   --;    
  }    
   
  return     tResult;    
  }    
   
  //   Read   a   big-endian   TYPE   from   address    
  template    
  F3D_INLINE   T   GetBigEndian(const   BYTE*     pBuf)    
  {    
  T   tResult   =   0;    
  for   (int     I   =   0;   I   <   sizeof(T);   ++   I)    
  {    
  tResult   <<=   8;    
  tResult   |=   *pBuf   ++;    
  }    
   
  return     tResult;    
  }    
   
  //   Set   a   little-endian   TYPE   on   a   address    
  template    
  F3D_INLINE   void   SetLittleEndian(BYTE*     pBuf,   T     t)    
  {    
  for   (int     I   =   0;   I   <   sizeof(T);   ++   I)    
  {    
  *pBuf   ++   =   BYTE(t   &   0xFF);    
  t   >>=   8;    
  }    
  }    
   
  //   Set   a   big-endian   T   on   a   address    
  template    
  F3D_INLINE   void   SetBigEndian(BYTE*     pBuf,   T     t)    
  {    
  pBuf   +=   sizeof(T)   -   1;    
  for   (int     I   =   0;   I   <   sizeof(T);   ++   I)    
  {    
  *pBuf   --   =   BYTE(t   &   0xFF);    
  t   >>=   8;    
  }    
  }    
   
  从上文可以看出,byte   order挺简单的,一般应用中可能也用不上,但若您对写跨平台的程序有兴趣,则一定要了解的比较清楚才行。以上代码都是从实际使用的源码中取下来的。      
   
  附:常见Processor,   OS的byte   ordering情况    
   
  Processor   OS   Order      
  x86   (Intel,   AMD,   …   )   All   little-endian      
  DEC   Alpha   All   little-endian      
  HP-PA   NT   little-endian      
  HP-PA   UNIX   big-endian      
  SUN   SPARC   All?   big-endian      
  MIPS   NT   little-endian      
  MIPS   UNIX   big-endian      
  PowerPC   NT   little-endian      
  PowerPC   non-NT   big-endian      
  RS/6000   UNIX   big-endian      
  Motorola   m68k   All   big-endian    
  Top

2 楼ykzhujiang(朱朱)回复于 2006-03-15 14:24:56 得分 5

处理的时候注意ntohs   ntohl之类的转换Top

3 楼tcww88(wuwei)回复于 2006-03-15 18:59:54 得分 0

ok  
  非常感谢楼上的朋友。  
  我的环境是slackware10.2,是little   endian的。  
  我做实验如下:  
  int   a=0x01020304;  
  char*   b=&a;  
  printf("a=%x\n",a);  
  printf("%x\n",*b);  
  printf("%x\n",*(b+1));  
   
  a=1020304  
  4  
  3  
   
  也就是说04放在最低地址,而指针指向04.  
  请问下我的分析对吗?Top

4 楼duduhaha(三人行必有我师)回复于 2006-03-15 19:34:38 得分 0

你说的是对的.应该是把最后一个字节放到一个short型的低位而不是高位.Top

相关问题

  • 字节序的问题
  • 从网络字节顺序转 换为本机字节顺序?
  • 什么叫网络字节顺序??
  • 关于字节序的疑惑
  • 字节顺序,motolora 和intel?急!!!!!!!!
  • 关于网络字节顺序问题
  • 关于网络字节顺序
  • 有谁知道,什么是主机字节顺序,网络字节顺序?(htons)
  • 主机字节顺序和网络字节顺序何时须转换
  • 网络字节顺序与本地机子字节顺序的转换问题(很简单的)

关键词

  • 代码
  • 转换
  • cpu
  • 数据
  • word
  • nt
  • endian
  • little
  • byte order
  • tresult

得分解答快速导航

  • 帖主:tcww88
  • duduhaha
  • ykzhujiang

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo