如何进行未定义的位移"correct"
How to make undefined bitshift "correct"
在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,则结果为零。
策略:
- 将偏移量右移 6 位,称为
temp
。 - 如果
temp
为零,我们希望将掩码初始化为所有 1 位,否则全部初始化为 0 位。我们可以通过设置mask = !!temp - 1
. - 现在只是按位
v
,offset
mask
.
实现:
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);
}
相关文章:
- 通过递归进行因子分解
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 使用libgit2、c++进行pull
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 如何使用模板函数的函数签名进行SFINAE
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- 将模板化的类型与C++中的某些类/类型进行比较
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 如何对点云数据进行排序
- 从文本文件中读取时钟时间和事件时间并进行处理
- 对字符串进行位操作
- 是否可以使用winusb同时与多个相同的usb设备进行通信
- 是否可以对零模板参数进行模板专门化
- 对字符串进行排序时,在c++中处理sort()
- 试图对缓存进行跨步测试,但程序并没有结束
- 如何进行未定义的位移"correct"