小端序和大端序问题

4

小端序与大端序

大端序 = 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 在其调试器中出现了严重错误,要么是我的整个机器..
因为我用一个更慢、冗余的代码替换了整个代码,但仍然得到相同的结果。
顺便说一句,如果有任何区别的话.. 我正在使用调试器在函数后面中断以检查结果。


2
@VirusEcks:展示你的完整程序,让一堆人猜测你所做的错误毫无意义。 - Steve Jessop
2
当你说“我使用返回值”时,你的意思是什么?该函数不会修改 y。你打印出来的值是 y。这个程序的输出肯定是“822167888”。如果你打印出 r,你会看到反转的字节序。 - Steve Jessop
1
@Steve:我们需要使用cout << hex,否则输出将会是十进制。 - Vlad
1
@VirusEcks:你好!你正在打印 y!为什么你认为你的函数 endian_swap 会以任何方式修改 y?它不会。 - Steve Jessop
抱歉让你感到困惑,其实我并不会将它打印出来,我会使用调试器在函数执行后中断并检查结果。 - VirusEcks
显示剩余5条评论
7个回答

2

您的代码似乎是正确的。

以下程序(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 << std::hex << r,否则你会打印(1)错误的变量和(2)十进制数 :-)

请参考这个例子: http://ideone.com/EPFz8


确实,它可以处理像这样的数字,但是对于这些十六进制数字,它会失败。 - VirusEcks
1
它是一个十六进制数。 :) 因此为 0x 12345678 - John
不幸的是,我正在使用Visual Studio编译器在Little-Endian系统上工作。 - VirusEcks
1
@Vlad:在Visual Studio上尝试过了,输出完全相同。 - Benjamin Lindley
@PigBen:谢谢!这证实了原帖中的函数工作正常。 - Vlad
显示剩余3条评论

2
  • 您是否正确地打印了结果?
  • 传递引用而不是值是否有影响?

移除引用会有影响吗?因为显然它没有:/ - VirusEcks
1
通常情况下,如果您想从函数内部更改传入的参数,则通过引用传递。从您的函数内部似乎根本没有更改 x,因此按值传递可以使您的意图更清晰(并且可能是正确的)。 :) - John
好的,这不是参考问题。有趣的问题! - John

1
在参数说明符前面消除“&”字符。你需要传递这个值。

@John:他们没有说,所以不可能知道,但这甚至没有解决所询问的问题。 - Roger Pate
有一段时间我们不确定它是否适用,但我认为现在我们已经弄清楚了,它并没有引起问题。 - John

0

位运算符并不实用,因为它们操作的方式是将位按照从最低有效位到最高有效位的顺序排列,而不考虑真正的内部字节顺序。

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。


0
你对你的代码进行了单元测试吗?
在我的平台上,这个通过了:
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); 
}

0
如果我运行您发布的代码,它会给出正确的结果: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的倍数? - VirusEcks
@Roger 我将IDE设置为自动格式化代码为4个空格缩进,所以如果我想手动格式化,请使用它。 - Pete Kirkham
@VirusEcks 一个十六进制数字(nibble)是4位,而不是8位。假设该代码使用f作为掩码以便处理十六进制数字,那么这个“4”会移动3个nibbles或12位。 - Pete Kirkham

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接