布尔表达式中的整数溢出

Integer overflow in boolean expressions

我有以下 C++ 代码:

#include <iostream>

using namespace std;

int main()
{
    long long int currentDt = 467510400*1000000;
    long long int addedDt = 467510400*1000000;
    if(currentDt-addedDt >= 0 && currentDt-addedDt <= 30*24*3600*1000000)
    {
                cout << "1" << endl;
                cout << currentDt-addedDt << endl;

    }       
    if(currentDt-addedDt > 30*24*3600*1000000 && currentDt-addedDt <= 60*24*3600*1000000)
    {
                cout << "2" << endl;
                cout << currentDt-addedDt << endl;

    }       
    if(currentDt-addedDt > 60*24*3600*1000000 && currentDt-addedDt <= 90*24*3600*1000000)
    {
                cout << "3" << endl;
                cout << currentDt-addedDt << endl;

    }       

   return 0;
}

首先,我收到一个整数溢出警告,这让我觉得很奇怪,因为数字 467510400*1000000 正好在 long long int 的范围内,不是吗?其次,我得到以下输出:

1
0
3
0

如果在这两种情况下 currentDt-addedDt 的计算结果为 0,那么第三个 if 语句怎么可能计算为真?

467510400*1000000long long范围内,但不在int范围内。由于两个文字都是 int 类型,因此产品的类型也是 int 类型 - 这将溢出。仅仅因为您将结果分配给 long long 不会更改分配的值。出于同样的原因,在:

double d = 1 / 2;

d 将保持 0.0 而不是 0.5

您需要将其中一个文字显式转换为更大的整数类型。例如:

long long int addedDt = 467510400LL * 1000000;
   long long int currentDt = 467510400ll*1000000ll;
   long long int addedDt = 467510400ll*1000000ll;

注意数字后面的两个小写字母 "l"。这些使您的常量变长。 C++ 通常将源代码中的数字串解释为纯 ints.

您遇到的问题是您所有的整数文字都是 int。当您将它们相乘时,它们会溢出,从而给您带来意想不到的行为。要更正此问题,您可以使用 467510400ll * 1000000ll

使它们成为 long long 文字

因为

60*24*3600*1000000 evaluates to -25526272

使用

60LL*24LL*3600LL*1000000LL

改为(注意 'LL' 后缀)

你已经用 C++ 标记了它。

我对你的代码的最小改动是使用 c++ static_cast 将至少一个文字数字(任何溢出生成表达式)提升为 int64_t(在包含文件 cstdint 中找到) .

示例:

//          0         true
if(currentDt-addedDt  >= 0     

&&   // true because vvvv

//          0        true
   currentDt-addedDt <= 30*24*3600*static_cast<int64_t>(1000000))
//                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(对于测试 1,if 子句的结果为真。 测试 2 和 3 为假)

找到 static_cast 后,编译器将其他 3 个整数(在子句中)提升为 int64_t,因此不会生成有关溢出的警告。

是的,它添加了很多字符,从某种意义上说,'minimal'。