C++:隐式常量转换中的溢出 [-Woverflow]

Posted

技术标签:

【中文标题】C++:隐式常量转换中的溢出 [-Woverflow]【英文标题】:C++ : overflow in implicit constant conversion [-Woverflow] 【发布时间】:2016-09-21 20:02:10 【问题描述】:
long long sum;
sum=pow(10,19);
cout<<sum;

C++ 中的上述代码给出了错误:

隐式常量转换中的溢出[-Woverflow]

虽然以下代码运行良好:

long long sum;
sum=pow(10,18);
cout<<sum;

可能是什么问题?

【问题讨论】:

10 的 19 次方是一个非常大的数字... “可能是什么问题?”显然是第二个数字参数。 【参考方案1】:

问题是long long太小,无法容纳pow(10,19)的结果。

long long 通常是 64 位,一个 64 位整数可以容纳大约 64 位整数。 1.8*10^19 个不同的值。然而,由于它是有符号的,你只能得到它的一半(另一半是负值)。而其中一半是0.9*10^19,显然小于10^19。

这里的另一个问题(但不是警告/溢出的原因)是pow() 函数返回一个浮点值。因此,即使结果适合 long long(它不适合),您也可能会丢失一些精度并且无法获得确切的整数结果。

编辑:当然,您可以在这种情况下使用unsigned long long。这对于 10 ^ 19 来说已经足够了,但对于 10 ^ 20 来说还不够。因此,当您使用不适合unsigned long long 的类似大数字时,您只是将问题推迟到以后。

【讨论】:

那么如果我想使用像 10^100 这样的结果,我应该如何存储它? 您应该将其存储为浮点值,例如floatdoublelong double,取决于您使用的 pow() 的版本。 @JesperJuhl 或boost multi-precision。我发现它非常易于使用(至少是任意长的整数部分,请参见页面末尾的示例here)。 @vsoftco - 当然有多种选择。我的观点只是,“当基本类型不够用时,使用任意精度库”,我只是举了一个例子。【参考方案2】:
log2(10^18) ~ 59.80
log2(10^19) ~ 63.12

签名的long long 可能是 64 位,其中 1 位为符号保留,因此 10^18 非常适合,但 10^19 不适合。

C++ 标准也只保证最大为2^63-1 的数字可以存储在long long 中。

pow 也在浮点上运行。其结果将不准确。因此,将其保存为整数很可能是一个错误。

【讨论】:

【参考方案3】:

long long 最大值仅为 9223372036854 775 807 pow(10,19) 是更大的数字 10000000000000000000

【讨论】:

以上是关于C++:隐式常量转换中的溢出 [-Woverflow]的主要内容,如果未能解决你的问题,请参考以下文章

错误:隐式常量转换溢出 [-Werror=overflow]

c++中的类型转换

C++ 数组中的多字节 UTF-8

为啥首先允许指针从非常量到常量的隐式转换?

将枚举转换为具有溢出的整数时会出现警告

记录: 一次解决整型溢出攻击(使用scala,隐式转换)