我怎样才能正确移动这个uint64_t数字?

时间:2017-03-20 19:16:42

标签: c bitwise-operators endianness

我正在编写一个小型测试程序,将64位数字从little-endian转换为big endian格式。

int main(void){
    uint64_t value1 = 1234;
    uint64_t value2 = 0;
    uint64_t constant = 0xFF00000000000000;
    uint8_t i;

    for(i = 0; i < 4; i++){
        int8_t shift = 56 - 16 * i;    // Gives me the sequence 56, 40, 24, 8.
        value2 |= (value1 & constant) >> shift;
        constant = constant >> 2;
    }

    for(i = 0; i < 4; i++){
        int8_t shift = 16 * i + 8;     // Gives me the sequence 8, 24, 40, 56.            value2 |= (value1 & constant) << shift;
        constant = constant >> 2;
    }

    printf("\n\nvalue1: %" PRIu64, value1);
    printf("\nvalue2: %" PRIu64, value2);
}

这有点令人费解,但这是我遇到问题的按位移位操作。这条线

constant = constant >> 2;

没有给我我的期望。我希望0xFF00000000000000在一个循环后成为0x00FF000000000000,依此类推。相反,它变为0x3FC0000000000000

我认为其他班次操作也存在类似的问题。谁能解释一下?

我的第一个猜测是,按位运算符只能在32位数字上正常工作。在这种情况下,我可以转换32位指针并一次处理一个32位块。但我想避免这种情况,因为它更令人费解。

2 个答案:

答案 0 :(得分:2)

这必须是在使用按位运算符时。请看下面简单的解释。

在您的情况下,0xFF0000...000实际上是0b111111110000...000二进制表示。当您必须读取二进制中的0000到1111时,实际上是十六进制表示中的0到F.这个按位运算符操作位级,因此在我们进一步研究之前,需要将这个十六进制表示分解为二进制。

现在移位2位给出0b001111111100...000。密切观察,这是0b<0011><1111><1100>00...000,实际上是0x3FC00...000

希望它解释一下!

答案 1 :(得分:0)

&gt;&gt;运算符按运算符右侧的位数进行位移。如果要移动超过1个字节(2个半字节),则应使用constant >> 8。无论应用移位的变量大小,它都完全相同。