large negative integer literals

-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

Leave a Comment