Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is "int i = 1;Why (i >= 60 * 60 * 1000 / 1 * 1000)" true?

First, defining two constant expressions without parentheses is my fault:

#define BIG_INTERVAL 60 * 60 * 1000
#define SMALL_INTERVAL 1 * 1000

int i = 1;

if (i >= BIG_INTERVAL / SMALL_INTERVAL - 1)
{
    printf("Oops!\n");
}

The if statement after the macro expansion is if(i >= 60 * 60 * 1000 / 1 * 1000 - 1).

That is not my intention. But I find something strange if I write if (i >= 3600000000 - 1). It is false.

What type is 60 * 60 * 1000 / 1 * 1000 - 1 ? int?

like image 435
Celebi Avatar asked Jul 14 '11 06:07

Celebi


4 Answers

All operators on ints return int. So yes, 60 * 60 * 1000 / 1 * 1000 - 1 is an int. But the expected result of 3599999999 is too big for an int, so the expression actually evaluates to -694967297 (assuming 32-bit int and two's complement).

This doesn't happen with a literal 3600000000 because integer literals larger than INT_MAX are of a type that can hold the full value.

like image 170
dan04 Avatar answered Nov 07 '22 20:11

dan04


60 * 60 * 1000 / 1 * 1000 - 1 = 3600000 * 1000 - 1, which overflows the int type, so the result can be anything (in your case it's negative, but it doesn't have to be).

To achieve what you want put ( ):

#define BIG_INTERVAL (60 * 60 * 1000)
#define SMALL_INTERVAL (1 * 1000)
like image 28
Petar Ivanov Avatar answered Nov 07 '22 20:11

Petar Ivanov


Here's my test results:

60 * 60 * 1000 / 1 * 1000 will result to -694967296

(60 * 60 * 1000) / (1*1000) will result to 3600

There's a problem with your operation, the precedence of computations.

You might want to consider looking at the C++ operator precedence http://msdn.microsoft.com/en-us/library/126fe14k%28v=vs.80%29.aspx. You'll find the reason why the result became -694967296 which I think effect of overflow.

like image 12
dpp Avatar answered Nov 07 '22 20:11

dpp


If you use a compiler where int is 64 bits, you will find that the result of your expression is false. If you use a compiler where int is 32 bits or 16 bits, your expression has undefined behaviour because overflow of signed ints doesn't have to wrap around. Probably yours did just wrap around, but it doesn't have to.

3600000000 is a constant visible at compile time, so if int is only 32 bits then your compiler will have to choose long long (or just long if long is 64 bits). So your other expression is evaluated with enough bits to avoid overflowing, and the result is correct.

like image 9
Windows programmer Avatar answered Nov 07 '22 19:11

Windows programmer