Step 1 of 8
Sizes and limits
So far you've mostly used int. C has a whole family of integer types, and professionals need to know exactly what each one can hold, because values that don't fit cause some of the nastiest bugs in C.
An integer of N bits can hold 2 to the power N different values. A signed 32-bit int spends one bit on the sign, giving a range of about -2.1 billion to +2.1 billion. C only promises minimum sizes, and the real sizes depend on the platform. On today's common systems:
| Type | Usual size | Range (signed) |
|---|---|---|
char |
1 byte | -128 to 127 |
short |
2 bytes | about ±32 thousand |
int |
4 bytes | about ±2.1 billion |
long |
4 or 8 bytes | depends on the platform! |
long long |
8 bytes | about ±9.2 × 10¹⁸ |
long is 8 bytes on 64-bit Linux and macOS, but 4 bytes on Windows and on 32-bit systems (including the WebAssembly this site runs on). Code that assumes one or the other breaks when it moves. That's why professional code uses the exact-width types you'll meet in a few steps.
Each type also has an unsigned version with no negative values and twice the positive range (a 32-bit unsigned int goes from 0 to about 4.29 billion).
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("short: %d to %d\n", SHRT_MIN, SHRT_MAX);
printf("unsigned int max: %u\n", UINT_MAX);
printf("long long max: %lld\n", LLONG_MAX);
long long big = 3000000000LL;
printf("%lld fits in long long\n", big);
return 0;
}
short: -32768 to 32767
unsigned int max: 4294967295
long long max: 9223372036854775807
3000000000 fits in long long
<limits.h> gives the real limits for the platform you compile on: INT_MAX, INT_MIN, LLONG_MAX, UINT_MAX, and CHAR_BIT (bits in a byte, 8 everywhere you'll ever work). Each type has its own printf specifier: %d int, %u unsigned, %ld long, %lld long long. A literal can be given a type with a suffix, like 3000000000LL.
Your turn: print the largest int, then the smallest.