Variables and types: why we use uint8_t
The size of int depends on the compiler. Why embedded code uses fixed-width types, plus signedness and overflow.
The C standard only says int is "at least 16 bits". It is 16 bits on an 8-bit AVR and 32 bits on an ARM Cortex-M. Registers and communication packets need an exact number of bits, so embedded code uses the fixed-width types from <stdint.h>.
Types you will use most
| Type | Size | Range |
|---|---|---|
uint8_t |
8 bits | 0 to 255 |
int16_t |
16 bits | -32768 to 32767 |
uint32_t |
32 bits | 0 to about 4.2 billion |
float |
32 bits | Fractions; fast if the MCU has an FPU |
Overflow
Put 255 in a uint8_t, add 1, and you get 0. For unsigned integers this wrap-around is defined behaviour. For signed integers overflow is undefined behaviour, and the compiler is allowed to do anything. A value that can grow, such as a variable that accumulates ADC readings, should be given a generous size from the start.
Working habits
- Registers, packets and raw sensor values always use fixed-width types
- Use
intonly where the size does not matter, such as a loop counter - Store a difference that can go negative in a signed type