integer width and fixed-width types
Every integer in a program lives in a box of a fixed number of bits, and the size of that box — its width — determines how large a value it can hold. A wider box reaches higher; a narrower box saves space but overflows sooner. Choosing the width is one of the everyday decisions of systems programming, and getting it wrong is a classic source of bugs that only appear on certain machines or with certain inputs.
The catch in plain C is that the basic types are deliberately vague about size. The standard only guarantees minimums and an ordering: a char is at least 8 bits, a short at least 16, an int at least 16 (commonly 32 today), a long at least 32, a long long at least 64. The actual sizes are implementation-defined, so the same int may be 32 bits on one platform and something else on another. To escape this uncertainty, C99 added the header stdint.h with fixed-width types that say exactly what they mean: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t — an exact width, signed or unsigned, on every conforming platform.
Use the fixed-width types whenever the size matters: parsing a file or network packet with a defined layout, packing bits, or guarding against overflow. Use size_t for sizes and array indices (it is the unsigned type wide enough to span any object), and intptr_t / uintptr_t for integers that must hold a pointer. The honest caveat: sizeof tells you a type's width in bytes AT COMPILE TIME for the machine you compile for, so never hard-code an assumption like 'int is 4 bytes' into a file format or a wire protocol — write the width down explicitly with a fixed-width type.
uint32_t always holds 32 unsigned bits (0 to 4294967295) on every platform, while plain int might be 16, 32, or 64 bits depending on the machine. For a network header, write uint32_t, never int.
stdint.h fixed-width types pin the size; the basic types do not.
sizeof is a compile-time operator that yields a size_t, not a runtime function; and sizeof(int) varies across platforms — relying on a specific value is non-portable, which is exactly why the fixed-width types exist.