按位移位*负数以反转数字中的位

时间:2019-02-13 21:20:13

标签: c shift

以负数执行按位移位是否有效? 例如,如果我有以下代码:

#include <stdint.h>
uint32_t reverse_bits (uint32_t n)
{
    uint32_t result = 0;    
    for (int i = 0; i < 32; i++) 
    {
        uint32_t bit = n & (1 << i);
        bit <<= 31 - i * 2;
        result |= bit;
    }
    return result;
}

这是我可以在所有体系结构上使用的东西吗(具体地说,其中x << shift_amt为真的表达式shift_amount < 0的结果等同于x >> -shift_amt)?

注意:这不是关于在负数(即-1 << 1)上执行按位移位的行为的问题。


这是完整的测试程序:

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
uint32_t reverse_bits (uint32_t n)
{
    uint32_t result = 0;
    for (int i = 0; i < 32; i++)
    {
        uint32_t bit = n & (1 << i);
        bit <<= 31 - i * 2;
        result |= bit;
    }
    return result;
}
void print_bits (uint32_t n)
{
    for (int i = 0; i < 32; i++)
        putchar(n & (1 << i) ? '1' : '0');
    putchar('\n');
}
int main ()
{
    for (int i = 0; i < 5; i++)
    {
        uint32_t x = rand();
        x |= rand() << 16;
        print_bits(x);
        print_bits(reverse_bits(x));
        putchar('\n');
    }
}

2 个答案:

答案 0 :(得分:8)

C标准声明在§ 6.5.7 paragraph 3:

中,移动负数是明确未定义的行为。
  

如果右操作数的值为负,或者大于或等于提升后的左操作数的宽度,则行为是不确定的。

强调我的。

答案 1 :(得分:3)

如前所述,按照undefined behavior第6.5.7p3节的规定,将负值移位会调用C standard

更改代码,而不是试图猜测何时可以摆脱负面影响,而不是去猜测。

屏蔽掉所需的位后,将其移回位置0,然后 将其移至所需位置。另外,请确保将常数1更改为1ul,以免最终将有符号的值移入符号位或超过int的宽度。还要注意使用sizeof来避免对魔术数字(例如32)进行硬编码。

unsigned long reverse_bits (unsigned long n)
{
    unsigned long result = 0;
    for (int i = 0; i < sizeof(unsigned long) * CHAR_BIT; i++)
    {
        unsigned long bit = ((n & (1ul << i)) >> i);
        unsigned long shift = (sizeof(unsigned long) * CHAR_BIT) - i - 1;
        result |= bit << shift;
    }
    return result;
}