Take a look at these variable declarations:
int a = 123; unsigned int b = 123; uint64_t c = 123;
We're using the same integer literal, 123
, to initialize three different integer types.
In practice, all three initializations work as you'd expect — a
, b
, and c
all end up initialized to the positive integer value one-hundred-and-twenty-three.
But what is the type of the literal 123
taken on its own?
The answer is, it depends.
If a literal is a decimal constant (e.g. 123
), its type is the first entry in the following list that can represent its value:
int
long int
long long int
If a literal is an octal or hexadecimal constant (e.g. 0123
or 0x123
), its type is the first entry in the following list that can represent its value:
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
Source: C11 Standard (N1570) 6.4.4.1.
There are no negative literals.
-123
isn't an integer literal — it's an expression consisting of the positive integer literal 123
and the unary negation operator -
.
You can add letter suffixes to specify a literal's type.
u
or U
makes the type unsigned
:
123u
— unsigned int
l
or L
makes the type long
:
123l
— long int
ll
or LL
makes the type long long
:
123ll
— long long int
Combinations work as expected:
123ul
— unsigned long int
123ull
— unsigned long long int
The stdint.h
header contains a set of function macros for adding the appropriate suffixes for fixed-width integer types.
Signed:
INT8_C()
INT16_C()
INT32_C()
INT64_C()
Unsigned:
UINT8_C()
UINT16_C()
UINT32_C()
UINT64_C()
For example UINT64_C(123)
will expand to 123ULL
or 123UL
, whichever is appropriate for the system.