lichenbo
lichenbo

Reputation: 1049

Why it is different between -2147483648 and (int)-2147483648

When I run the following code under Windows7 x64, compiled with GCC of MinGW, the result seems to be underflowed:

cout<<-2147483648 ;    //Output: 2147483648

but when I assigned it to a integer variable, or just simply convert it to the int type :

cout<<(int)-2147483648 ; //Output: -2147483648 

So, what's wrong with the previous version of my code? Istn't it the type int? or what the lower bound the Integer is exactly? Many thanks.

Upvotes: 10

Views: 7332

Answers (4)

lichenbo
lichenbo

Reputation: 1049

Actually I found an explaination from a pdf file of CS:APP which perfectly give the solution, you can download it from here. http://www.csapp.cs.cmu.edu/public/waside/waside-tmin.pdf

Upvotes: 0

Lundin
Lundin

Reputation: 214930

First of all, it is important to understand that there are no negative integer literals.

Others have explained why the OP's particular compiler behaves as it does. But for the record, this is what the compiler should do, between the lines, on a 32-bit system:

  • You have the number 2147483648, which cannot fit in a 32-bit signed int of two's complement format.
  • Since it is a decimal number (without an U, L or similar suffix), the compiler checks its internal type table (1) for such an integer constant. It works like this: try to fit it in an int, if it doesn't fit, try a long, if it doesn't fit there either, try a long long, if it doesn't fit there either, we have undefined behavior. A C or C++ compiler following the latest standard will not attempt to fit it in unsigned types.
  • In this specific case, the number doesn't fit in an int nor in a long, so the compiler decides to use a long long as type for the literal.
  • You then use the unary minus operator on this literal, ending up with the number -2147483648. Ironically this would fit in a signed int of two's complement format, but it is too late to change the type, the compiler has already picked long long as the type.

(1) This "internal table" looks different if you have an unsigned suffix, or if you have hex format etc. If there is an unsigned suffix, it will only check if the number fits in unsigned numbers. If there is hex notation (but no suffix), it will check int, then unsigned int, then long and so on.

Upvotes: 2

Mike Seymour
Mike Seymour

Reputation: 254721

So, what's wrong with the previous version of my code?

Presumably, you're using a pre-2011 compiler, and on your system long has 32 bits. The value (-231) isn't guaranteed to fit into long, so it might overflow. That gives undefined behaviour, so you could see anything.

The most likely explanation for the particular value you see (231) is that, in the absence of defined behaviour in C++, your compiler is using the old C90 rules, and converting the value to unsigned long.

Istn't it the type int?

Before 2011, it was int if the value is representable by int, otherwise long, with undefined behaviour if that isn't sufficient. C++11 adds the long long type, and allows that to be used for integer literals if long isn't big enough.

or what the lower bound the Integer is exactly?

Signed integer types with N bits have a range of at least -2(N-1)+1 to 2(N-1)-1. Your value is -231, which is just out of range for a 32-bit signed type.

The language doesn't specify the exact size of the integer types; just that int must have at least 16 bits, long at least 32, and (since 2011) long long at least 64.

Upvotes: 3

user743382
user743382

Reputation:

2147483648 doesn't fit into an int or a long on your system, so it's treated as a constant of type unsigned long. (Edit: as ouah pointed out in the comments, it's undefined behaviour in standard C++, but your compiler accepts it as an extension.) Negating an unsigned integer value is possible, but results in another unsigned integer value, never a negative number. Negating 2147483648UL produces 2147483648UL (assuming, as is the case on your system, that unsigned long is a 32 bit type).

Casting that to int produces an implementation-defined result, commonly the result you see, but not necessarily. You can get the result you want without any conversions by writing -2147483647 - 1.

Upvotes: 11

Related Questions