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.