You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

uint64_t左移运算异常求助:赋值方式不同结果差异问题

为什么mask << (64 - shamt)当shamt为0x0时没得到预期的0?

这个问题其实踩中了C/C++位运算里一个很容易忽略的坑——无符号整数左移位数等于或超过类型位数时,行为是未定义的

咱们拆解一下你的代码:

  • shamt被赋值为0x0,也就是十进制的0,所以64 - shamt的结果是64。
  • maskuint64_t类型,刚好是64位的无符号整数。

根据C/C++标准的规定:对于无符号整数类型的左移操作a << n,只有当n满足0 ≤ n < 类型的位数时,行为才是明确的——将a的二进制位左移n位,右侧补0。但如果n ≥ 类型的位数,这个操作的行为就是未定义的

这就解释了为什么你看到的结果不符合预期:编译器遇到这种未定义行为时,完全可以按照它自己的逻辑处理——有的编译器可能直接返回原数,有的可能返回0,甚至可能做其他奇怪的操作。你提到“将shamt赋值为十进制0时结果符合预期”,这其实只是你所用编译器在特定编译条件下的巧合表现,并不是标准要求的行为,换个编译器或者编译选项可能结果就不一样了。

那怎么解决这个问题,确保得到预期的结果呢?很简单,显式处理移位位数等于64的边界情况:

#include "iostream"
#include <cstdio>
int main(int argc, char const *argv[]) {
 uint64_t shamt = 0x0;
 uint64_t mask = 0xffffffffffffffff;
 uint64_t result;
 if (64 - shamt >= 64) {
     // 移位位数等于或超过64位,直接返回0
     result = 0;
 } else {
     result = mask << (64 - shamt);
 }
 printf("mask << (64 - shamt): %016lx\n", result);
 return 0;
}

这样就能保证不管shamt取什么值,都能得到符合你预期的结果,同时避免触发未定义行为。

内容的提问来源于stack exchange,提问作者user8453362

火山引擎 最新活动