【问题标题】:How can I correctly shift this uint64_t number?我怎样才能正确地移动这个 uint64_t 数字?
【发布时间】:2017-03-20 19:16:41
【问题描述】:

我正在编写一个小测试程序,将 64 位数字从小端格式转换为大端格式。

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 位块。但我想避免这种情况,因为它更加复杂。

【问题讨论】:

  • constant &gt;&gt; 2 将数字向右移动两个
  • 移动一个字节:constant &gt;&gt; 8
  • 注意:将变量称为“常量”可能不是一个好主意。
  • 循环为 for(i = 0; i &lt; 4; i++) 会让你省去神奇的数字 72
  • 为什么 64 位类型的移位运算符会有限制? (反问,当然没有)。您的指针方法 otoh 会调用未定义的行为。

标签: c bitwise-operators endianness


【解决方案1】:

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

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

现在移动 2 位给出0b001111111100...000。仔细观察,这是0b&lt;0011&gt;&lt;1111&gt;&lt;1100&gt;00...000,实际上是0x3FC00...000

希望它解释清楚!

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 绝对是一个捂脸的情况。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-06-15
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 2018-07-15
    • 2013-03-22
    相关资源
    最近更新 更多