Since we're supporting everything from 16-bit (c99 for older tools chains) to 32/64-bit chips, using int or long is asking for trouble. Their sizes change depending on the CPU, which breaks our struct layouts and wastes RAM on padding. We should swap out for uint8_t, uint32_t, etc., and uintptr_t is specifically designed to match the pointer width on the target hardware (2 bytes on 16-bit, 4 on 32-bit, etc.).
| Original Type |
Fixed-Width Replacement |
Size (Bits) |
Best Use Case |
| unsigned char |
uint8_t |
8 |
Buffers, small IDs, and raw bytes. |
| unsigned short |
uint16_t |
16 |
16-bit sensor data and 16-bit registers. |
| unsigned int |
uint32_t |
32 |
Standard integers, counters, and IPv4. |
| int |
int32_t |
32 |
Signed math where 32-bit range is needed. |
| unsigned long |
uint32_t or uint64_t |
32 or 64 |
Danger: Size varies by CPU. Pick a fixed width. |
| void * (as int) |
uintptr_t |
Variable |
Safely storing an address as an integer |
Since we're supporting everything from 16-bit (c99 for older tools chains) to 32/64-bit chips, using int or long is asking for trouble. Their sizes change depending on the CPU, which breaks our struct layouts and wastes RAM on padding. We should swap out for uint8_t, uint32_t, etc., and uintptr_t is specifically designed to match the pointer width on the target hardware (2 bytes on 16-bit, 4 on 32-bit, etc.).