-2147483648
, for example, is not an integer literal. It's an expression consisting of a unary -
operator applied to the literal 2147483648
.
Prior to the C++ 2011 standard, C++ didn't require the existence of any type bigger than 32 bits (C++2011 added long long
, which is at least 64 bits), so the literal 2147483648
was non-portable.
A decimal integer literal is of the first of the following types in which its value fits:
int
long int
long long int (C++ 2011 and later)
Note that it's never of an unsigned type in standard C++. In pre-2011 editions of the C++ standard (which didn't have long long int
), a decimal integer literal that's too big to fit in long int
resulted in undefined behavior -- but you're unlikely to have to worry about that. In C++2011 and later, if a decimal integer literal doesn't fit in long long int
, then the program is "ill-formed".
Some very old versions of g++ didn't implement the C++2011 semantics. For example, g++ 4.6.1 (the version on which I based the original version of this answer) treated the literal 2147483648
as a constant of type unsigned long
. (See the edit history of this question for more out-of-date information.)
Here's a small program that you can use to show how your compiler treats literals:
#include <iostream>
#include <climits>
const char *type_of(int) { return "int"; }
const char *type_of(unsigned int) { return "unsigned int"; }
const char *type_of(long) { return "long"; }
const char *type_of(unsigned long) { return "unsigned long"; }
const char *type_of(long long) { return "long long"; }
const char *type_of(unsigned long long) { return "unsigned long long"; }
int main()
{
std::cout << "int: " << INT_MIN << " .. " << INT_MAX << "\n";
std::cout << "long: " << LONG_MIN << " .. " << LONG_MAX << "\n";
std::cout << "long long: " << LLONG_MIN << " .. " << LLONG_MAX << "\n";
std::cout << "2147483647 is of type " << type_of(2147483647) << "\n";
std::cout << "2147483648 is of type " << type_of(2147483648) << "\n";
std::cout << "-2147483647 is of type " << type_of(-2147483647) << "\n";
std::cout << "-2147483648 is of type " << type_of(-2147483648) << "\n";
}
When I compile and execute it (with g++ 11.3.0 on 64-bit Ubuntu) I get:
int: -2147483648 .. 2147483647
long: -9223372036854775808 .. 9223372036854775807
long long: -9223372036854775808 .. 9223372036854775807
2147483647 is of type int
2147483648 is of type long
-2147483647 is of type int
-2147483648 is of type long
std::cout
probably is not promoting those literals as you'd expect. – Hivesnumeric_limits<int>::min()
he's using hard coded literals which will be whatever the compiler uses by default. – Hivesnumeric_limits
as comments to make clear what the compiler uses, and his values were correct – Kidding