Cannot assign the value of INT_MIN to a long long
Asked Answered
K

3

5
signed long long value = -2147483648;
    cout << ((signed long long)value);

outputs 2147483648 (no minus sign), why?

Karli answered 4/4, 2011 at 9:37 Comment(3)
Is the title really supposed to say what it does?Alrzc
@Erik: well, INT_MIN is -2147483648 on my implementation. On a sign-magnitude implementation, INT_MIN would be OK (since for example if it's -2147483647, then 2147483647 is representable as an int), and INT_MIN-1 would be the first potential problem.Damiendamietta
long long is not a "built-in-type" until C++0x.Prud
C
9
signed long long value = -2147483648;

2147483648 cannot be represented in a 32-bit signed integer, so it is converted to an unsigned, then unary minus is applied (which doesn't change anything), and then it is assigned to the signed long long. Use -2147483648LL

Che answered 4/4, 2011 at 9:40 Comment(8)
@Mitch: The literal isn't a signed long long. The variable is.Che
@Che yes it does work with LL (long long I suppose), are there any other "postfix" to a literals?Karli
But the original code works differently on g++. Isn't that covered in the standard?Package
L for long, U for unsigned, UL for unsigned long. LL and ULL are not really C++ - but supported in many compilers as it is C99. Then you have float suffixes, F for float and L for long doubleChe
Oh, it's because ints are 64 bit on my machine. Sorry.Package
If you were worried about LL not being supported (even though long long is), then you could use -(long long)2147483648. But it would be rather strange for a C++ compiler to support long long as an extension but not also support LL.Damiendamietta
@Erik: It looks like in this implementation the value is treated as unsigned int, but in the standard, behaviour is undefined if the value cannot be represented as long (2.13.1/2). The standard never makes decimal integer literals with no suffix unsigned.Damiendamietta
@Steve Jessop: Ah yes, the unsigned integrals would only be guaranteed for hex/oct literals. So it is UB.Che
L
1

A literal integer, in C++, has the type int. If it doesn't fit into that type, it may be interpreted as an unsigned integer. However, it is not guaranteed that it automatically will be treated as a larger integer type.

The standard, fortunately, support a suffix notation to specify the explicit type of the literal.

In this case, you should use -2147483648LL.

Lynd answered 4/4, 2011 at 9:47 Comment(2)
"it is not guaranteed that it automatically will be treated as a larger integer type." - well, 2.13.1/2 guarantees that it will be treated as long int, but that might well be no larger than int.Damiendamietta
The standard does not support LL until C++0x.Prud
I
0

Your original code may contain undefined behavior, but it looks more like a compiler bug to me. As others have pointed out, the constant 2147483648 cannot be represented in a 32 bit int. According to the standard, "The type of an integer literal depends on its form, value, and suffix. If it is decimal and has no suffix, it has the first of these types in which its value can be represented: int, long int; if the value cannot be represented as a long int, the behavior is undefined." The draft C++0x adds long long at the end of these.

If LONG_MAX is greater than 2147483648, then the type of the literal is long, and the minus should give the correct value. Otherwise, if the compiler already supports long long (and since you're declaring a variable of this type, one must assume that it does), the type of 2147483648 is long long, and the minus should give the correct value. If the compiler doesn't support long long, and long is only 32 bits, then your code has undefined behavior, so anything the compiler does is "correct".

Immunoreaction answered 4/4, 2011 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.