【问题标题】:Little Endian - Big Endian Problem小端 - 大端问题
【发布时间】:2011-05-09 08:07:50
【问题描述】:

小端与大端

大端 = 0x31014950
小尾数 = 0x50490131

但是使用这种方法

inline unsigned int endian_swap(unsigned int& x)  
{
return ( ( (x & 0x000000FF) << 24 ) | 
         ( (x & 0x0000FF00) << 8  ) |
         ( (x & 0x00FF0000) >> 8  ) |
         ( (x & 0xFF000000) >> 24 ) );
}

结果 = 0x54110131
我花了很多时间尝试了很多类似的方法,甚至像

这样的库
unsigned long _byteswap_ulong(unsigned long value);  

但仍然没有运气.. 都返回相同的结果

编辑
我正在使用 Microsoft Visual Studio 2008 开发 Little-Endian 系统
示例如下

int main()
{
    unsigned int y = 0x31014950;
    unsigned int r = endian_swap( y );
    std::cout << r;
}  

在 Ideone.com 上发布的示例是正确的 .. 但它不适用于我

编辑

std::cout << std::hex << r;  

无论是朋友.. 十六进制与否,它都没有得到正确的数字.. Visual Studio 的调试器或我的整台机器出现严重错误..
因为我用更慢的冗余代码替换了整个代码,但仍然得到相同的结果
顺便说一句,如果它有任何区别..我在函数之后使用调试器来中断来检查结果

【问题讨论】:

  • 你使用的是返回值,对吧?当您引用 x 时,您从未实际修改它。
  • @VirusEcks:展示你的完整程序,一群人围坐在一起猜测你做错了什么是没有意义的。
  • 所以当你说“我使用return”时,你是什么意思?该函数不会修改y。你打印出来的值是y。这个程序的输出肯定是“822167888”。如果你打印出r,你会看到字节序反转的值。
  • @Steve: 我们需要cout &lt;&lt; hex,否则我们得到十进制输出
  • @VirusEcks:你好!您正在打印y!为什么您会认为您的函数endian_swap 会以任何方式修改y?它没有。

标签: c++ endianness


【解决方案1】:

位运算符没有用处,因为它们的操作就像位按从最低有效位到最高有效位的顺序排列一样,而不管真正的内部字节顺序如何。

void isBigEndian()
{
    void *number;
    number = (int *) new int(0x01000010);
    // 0x01000010
    //   01 00 00 10                                      Hexadecimal
    //   0    1      0    0      0    0       1    0
    //   0000 0001   0000 0000   0000 0000    0001 0000   Bit
    //   1           0           0            16          Decimal
    char *byte;
    byte = (char *)number;
    cout << static_cast<int>(*byte);//prints 16: Little Endian
}

你改变上面的数字,让它在 BigEndian 时返回 1。

【讨论】:

    【解决方案2】:

    如果我运行您发布的代码,它会给出正确的结果:endian_swap ( 0x31014950 ) == 0x50490131

    要得到结果:endian_swap ( 0x31014950 ) == 0x54110131,您的代码必须等同于:

    #define __
    inline unsigned int endian_swap(unsigned int& x)  
    {                  //0x31014950  ->            0x54110131
        return  ( ( (x & 0x000000FF) << 24 ) |   //  50
            __    ( (x & 0x00F0F000) << 12 ) |   //   4
            __    ( (x & 0x00FF0000) << 4  ) |   //    1  
            __    ( (x & 0x00FF0000) << 0  ) |   //     1  
            __    ( (x & 0x00FF0000) >> 8  ) |   //      01
            __    ( (x & 0xFF000000) >> 24 ) );  //        31        
    }
    

    检查您的代码中是否也没有类似的差异。

    【讨论】:

    • 我很感兴趣 .. 怎么是 12 .. 而不是 8 的乘积?
    • @Roger 我将 IDE 设置为自动格式化代码为 4 个空格缩进,所以如果我想手动格式化,请使用它。
    • @VirusEcks 一个十六进制数字(半字节)是 4 位,而不是 8。假设代码使用 f 作为掩码以便处理半字节,则 4 移动 3 半字节或 12 位。
    【解决方案3】:

    您编辑的示例输出的是 y 而不是 r。当然,输入 y 没有被修改。

    【讨论】:

      【解决方案4】:

      您的代码似乎是正确的。

      以下程序(http://ideone.com/a5TBF):

      #include <cstdio>
      
      inline unsigned int endian_swap(unsigned const int& x)  
      {
      return ( ( (x & 0x000000FF) << 24 ) | 
               ( (x & 0x0000FF00) << 8  ) |
               ( (x & 0x00FF0000) >> 8  ) |
               ( (x & 0xFF000000) >> 24 ) );
      }
      
      int main()
      {
          unsigned int x = 0x12345678;
          unsigned int y = endian_swap(x);
          printf("%x %x\n", x, y);
          return 0;
      }
      

      输出:

      12345678 78563412


      编辑:
      你需要std::cout &lt;&lt; std::hex &lt;&lt; r,否则你打印(1)错误的变量,(2)十进制:-)

      见这个例子:http://ideone.com/EPFz8

      【讨论】:

      • 确实 .. 它适用于这样的数字 .. 但使用这个十六进制数字它会失败 ..
      • 一个十六进制数。 :) 因此 0x 12345678
      • 不幸的是,我正在使用 Visual Studio 编译器开发 Little-Endian 系统
      • @VirusEcks:你能用 Visual Studio 试试同样的例子吗?
      • @Vlad:在 Visual Studio 上试过,输出完全一样。
      【解决方案5】:

      您是否对代码进行了单元测试?

      在我的平台上,这通过了:

      void LittleEndianTest::testLittleEndian()
      {
          unsigned int x = 0x31014950;
          unsigned int result = 
               (
                   ( (x & 0x000000FF) << 24 ) + 
                   ( (x & 0x0000FF00) << 8  ) +
                   ( (x & 0x00FF0000) >> 8  ) +
                   ( (x & 0xFF000000) >> 24 ) 
               );
      
          CPPUNIT_ASSERT_EQUAL((unsigned int)0x50490131, result); 
      }
      

      【讨论】:

        【解决方案6】:
        • 您打印的结果正确吗?
        • 您传递的是引用而不是值这一事实是否会产生影响?

        【讨论】:

        • 去掉引用会有什么不同吗?因为显然它没有:/
        • 如果你想从函数内部改变传入的参数,通常你通过引用传入。您似乎根本没有从您的函数中更改x,因此按值传递会使您的意图更清晰(并且可能是正确的)。 :)
        • 好吧,这不是参考的东西。有趣的问题!
        【解决方案7】:

        消除参数说明符中 x 前面的 & 符号。你想传递值。

        【讨论】:

        • @John:他们没有说,所以不可能知道,但这甚至不能解决所问的问题。
        • 有一段时间不清楚它是否适用,但我想我们现在已经弄清楚它并没有导致问题。
        猜你喜欢
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-30
        • 2016-06-13
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多