Bigendian / Littleendian混乱

时间:2011-03-26 17:53:32

标签: c++

我正在处理为ipv4编写的遗留代码。现在我已经为ipv6添加了类似的代码。我已经在主机上试过并测试了..但是我担心它是否会在powerpc上工作,因为有字节序...代码是从传入的流中提取ip头并压缩它..任何评论都会有帮助

class st_ipv6
{
  //==================================================================================================
public:
  //==================================================================================================

#ifdef _BIG_ENDIAN
  uint32  version:4;              // version 
  uint32  trafficclass:8;         // header length 
  uint32  flowlabel:20;           // flow label
#else
  uint32  trafficclass_1:4;
  uint32  version:4;              // version 
  uint32  flowlabel_1:4; 
  uint32  trafficclass_2:4;         // traffic class
  uint32  flowlabel_2:4;           // flow label 
  uint32  flowlabel_3:4;           // flow label 
  uint32  flowlabel_4:4;           // flow label 
  uint32  flowlabel_5:4;           // flow label 
#endif
  uint16  payloadlength;          // payload length
  uint8   nextheader;             // next header
  uint8   hoplimit;               // hop limit
  uint32  sourceaddress[4];       // source address 
  uint32  destinationaddress[4];  // destination address 




#ifdef _BIG_ENDIAN
  //**********************************************************************************************
  //* Description:
  /**  Specify/Return IPv6 Version
  */
  //**********************************************************************************************
  inline void setVersion(uint8 ubyVersion)
  {
    version = ubyVersion;
  }
  inline uint8 getVersion()
  {
    return version;
  }

4 个答案:

答案 0 :(得分:3)

Bitfields和便携性通常是一场噩梦。通常最好使用和/或/ shift。

参见例如下方。

只要在读/写时对各种整数调用hton *()/ ntoh *(),你就会(希望)没有问题。

我还会编写其余的访问器并将数据字段设为私有。

class st_ipv6
{
public:
    uint32 version_info;
    uint16 payloadlength;          
    uint8  nextheader;             
    uint8  hoplimit;               
    uint32 sourceaddress[4];       
    uint32 destinationaddress[4]; 

    uint8 GetVersion() 
    { 
        return version_info & 0xF; 
    }
    void  SetVersion(uint8 v) 
    {
        version_info = (version_info & ~0xF) | (v & 0xF);
    }
    uint8 GetTrafficClass() 
    { 
        return (version_info & 0xFF0)>>4; 
    }
    void  SetTrafficClass(uint8 c) 
    {
        version_info = (version_info & ~0xFF0) | ((c & 0xFF) << 4);
    }
    uint32 GetFlowLabel() 
    { 
        return (version_info & 0xFFFFF000)>>12; 
    }
    void  SetFlowLabel(uint32 f) 
    {
        version_info = (version_info & ~0xFFFFF000) | ((f & 0xFFFFF) << 12);
    }
};

答案 1 :(得分:1)

我建议使用struct而不是class,因为RTTI可以在内存布局中插入额外的内容。

我认为这应该足够了

#ifdef _BIG_ENDIAN
  uint32  version:4;              // version 
  uint32  trafficclass:8;         // header length 
  uint32  flowlabel:20;           // flow label
#else
  uint32  flowlabel:20;           // flow label
  uint32  trafficclass:8;         // header length 
  uint32  version:4;              // version 
#endif

...但您在阅读流程标签时应ntohl(flowlabel),在设置时应htonl(flowlabel)

答案 2 :(得分:0)

小心使用不同的编译器并使用位域。一些编译器在高位开始位域并向下工作,而其他编译器从低位开始工作。除非您仔细测试正在使用的不同编译器,否则最好自己从原始字节中进行屏蔽。

答案 3 :(得分:0)

非常感谢迈克尔。基于输入我编写了一个简单版本的函数,并尝试进行基本测试,它看起来没有版本字段。我的程序看起来像这样。现在唯一关心的是,当我们有像src和dst地址

这样的uint32数组时

class ip_v6 {

公共:    uint32 version_info;    uint16 payload_len;    uint8 next_header;    uint8 hop_limit;    uint32 src_addr [4];    uint32 dst_addr [4];

uint32 GetVersionInfo()    {       return(ntohl(version_info));    }

void SetVersionInfo(uint32 vinfo)    {       version_info = htonl(vinfo);    }

uint8 GetVersion()    {       return(((GetVersionInfo())&amp;(0xf0000000))&gt;&gt; 28);    }

void SetVersion(uint8 v)    {       SetVersionInfo((GetVersionInfo()&amp; 0x0fffffff)|(v <&lt; 28));    }

uint8 GetTrafficClass()    {       return(((GetVersionInfo())&amp;(0x0ff00000))&gt;&gt; 20);    }

void SetTrafficClass(uint8 c)    {       SetVersionInfo((GetVersionInfo()&amp; 0xf00fffff)|(c <&lt; 20));    }

uint32 GetFlowLabel()    {       return((GetVersionInfo())&amp;(0x000fffff));    }

void SetFlowLabel(uint32 f)    {       SetVersionInfo((GetVersionInfo()&amp; 0xfff00000)|(f));    } };