按位移位*负数以反转数字中的位
Bitwise shift *by* a negative number to reverse the bits in a number
按位移位负数是否有效?
例如,如果我有以下代码:
#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 paragraph 3:
中明确未定义的行为
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
强调我的。
如前所述,移动负值会调用 undefined behavior as per section 6.5.7p3 of the 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;
}
按位移位负数是否有效? 例如,如果我有以下代码:
#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 paragraph 3:
中明确未定义的行为If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
强调我的。
如前所述,移动负值会调用 undefined behavior as per section 6.5.7p3 of the 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;
}