如何进行未定义的位移"correct"

How to make undefined bitshift "correct"

本文关键字:correct 何进行 未定义      更新时间:2023-10-16

在C++中,将n位整数移位n是未定义的行为:

std::uint64_t v = 1;
v = v << 64; // Undefined behaviour
std::cout << v << std::endl;

上面的代码在我的机器上打印1。这种位移的"正确"结果应该是 0,一个天真的修复是使用分支:

std::uint64_t v = 1;
std::uint64_t offset = 64;
v = offset >= 64 ? 0 : v << offset;
std::cout << v << std::endl;

有没有办法在不使用分支的情况下获得相同的结果?

是的。

我们希望修复问题,以便如果offset大于或等于 64,则结果为零。

策略:

  1. 将偏移量右移 6 位,称为temp
  2. 如果temp为零,我们希望将掩码初始化为所有 1 位,否则全部初始化为 0 位。我们可以通过设置mask = !!temp - 1.
  3. 现在只是按位voffsetmask.

实现:

uint64_t shift(uint64_t value, uint64_t offset) {
uint64_t temp = offset >> 6;
uint64_t mask = (!!temp) - 1;
return (value & mask) << (offset & mask);
}

与其offset,您还可以按位移动 - 并且带有~0x3F,可能会更快。

uint64_t shift(uint64_t value, uint64_t offset) {
uint64_t mask = (!!(offset & ~0x3F)) - 1;
return (value & mask) << (offset & mask);
}