布尔表达式中的整数溢出

时间:2015-10-27 19:59:09

标签: c++ overflow boolean-logic boolean-expression

我有以下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 int的范围内,不是吗?其次,我得到以下输出:

1
0
3
0

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

5 个答案:

答案 0 :(得分:5)

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

double d = 1 / 2;

d将保留0.0而非0.5

您需要明确地将其中一个文字强制转换为更大的整数类型。例如:

long long int addedDt = 467510400LL * 1000000;

答案 1 :(得分:0)

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

请注意数字后面的两个小写字母“l”。这些使你的常数很长。 C ++通常将源中的数字字符串解释为普通int s。

答案 2 :(得分:0)

您遇到的问题是所有整数文字都是int。当你将它们相乘时,它们会溢出,给你意想不到的行为。要解决此问题,您可以使用long long

制作467510400ll * 1000000ll文字

答案 3 :(得分:0)

因为

60*24*3600*1000000 evaluates to -25526272

使用

60LL*24LL*3600LL*1000000LL
而是(请注意&#39; LL&#39;后缀)

答案 4 :(得分:0)

您已使用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子句的结果为true。  对于测试2和3是错误的)

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

是的,它在某种意义上增加了许多字符,“最小”。