【问题标题】:Unsigned long long overflow error?无符号长长溢出错误?
【发布时间】:2014-06-01 02:18:03
【问题描述】:

我在使用 unsigned long long 时遇到了一些奇怪的问题。

当我设置一个 unsigned long long 时会发生这种情况(我使用了 size_t,但是这个问题可以用 u-l-l 重复)。我已将其设置为 2^31,但由于某种原因,它恢复为 18446744071562067968 或 2^64 - 2^31。请记住,我使用的是 x64 编译:

unsigned long long a = 1 << 31;
cout << a;

//Outputs 18446744071562067968, Expected 2147483648

我以为 u-l-l 的极限是 2^64-1?那么为什么不能存储 2^31 呢? 2^30 工作得很好。 Sizeof(a) 返回 8,如果我没记错的话是 64 位,证明了 2^64-1 的限制。

我正在 Visual C++ 2013 Express Desktop 上编译。

我唯一的猜测是这是某种溢出错误,因为它不适合正常的长类型。

【问题讨论】:

  • 提示:1&lt;&lt;31 是一个int 表达式。不长,不是未签名。
  • 谢谢,这解释了限制......那么还有另一种方法可以在 long long 上执行二进制操作吗?
  • 1ULL
  • 或long long n = 1; long long a = n &lt;&lt; 31; 类型如uint64_t from stdint.h 保证整数的长度。
  • 要记住的是,表达式(包括子表达式)的类型通常由表达式本身决定,而不是由它出现的上下文决定。

标签: c++ visual-c++ integer-overflow unsigned-long-long-int


【解决方案1】:

当负整数值分配给 unsigned long long 时,您看到的是符号扩展。

要修复它,您需要将值设为无符号开头,如下所示:

#include <iostream>
#include <iomanip>

int main()
{
    unsigned long long a = 1ull << 31ull;
    std::cout << a << "\n";
    std::cout << std::hex << a << "\n";

    return 0;
}

如果您将警告级别设置得足够高 (/W4),您会看到有关有符号/无符号不匹配的警告。

为了完整起见,您不需要限定两个参数,只需左操作数就可以了,所以unsigned long long a = 1u &lt;&lt; 31; 可以工作。我只是更喜欢尽可能明确。

【讨论】:

  • 使用 OP 的原始代码在 g++ 中没有警告;也许微软不一样
  • 对我也没有任何警告......不过感谢您的帮助。
  • 这是 Visual Studio 中的 4 级警告,因此您可能将警告设置得较低。我相信你需要-Wconversion 才能在 gcc 中看到警告。
  • 1ull &lt;&lt; 31中的31不需要后缀ull。与大多数二元运算符的结果类型由两个操作数的类型决定不同,a &lt;&lt; b 的类型仅由a 的类型决定(而int 足以表示31)。跨度>
  • 啊,这正是我正在编辑的内容。我通常在所有内容中添加后缀,以避免在更复杂的表达式中移动时出现问题。
猜你喜欢
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多