c - 按位移位 *by* 一个负数以反转数字中的位

  • 本文关键字:数字 一个 by 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');
    }
}

C 标准在 § 6.5.7 第 3 段中声明负数移位是明确未定义的行为:

如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

强调我的。

如前所述,根据 C 标准第 6.5.7p3 节,按负值移动会调用未定义的行为。

与其试图猜测何时可以摆脱负变化,不如更改代码,这样你就不需要了。

遮盖掉所需的位后,将其移回位置 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;
}

最新更新