The compiler may align any (scalar) object as it pleases unless it is part of an array or similar, there's no restriction or guarantee from C. Arrays are guaranteed to be allocated contiguously however, with no padding. And the first member of a struct/union is guaranteed by be aligned (since the address of the struct/union may be converted to a pointer to the type of the first member).
To get atomic operations, you have to use something like atomic_uint_fast16_t
(stdatomic.h) if supported by the compiler. Otherwise any operation in C cannot be regarded as atomic no matter the type, period.
It is a common mistake to think "8 bit copy is atomic on my CPU so if I use 8 bit types my code is re-entrant". It isn't, because uint8_t x = y;
is not guaranteed to be done in a single instruction, nor is it guaranteed to result in atomic machine code instructions.
And even if an atomic instruction is picked, you could still get real-time bugs from code like that. Example with pseudo-machine code:
- Store the contents of
y
in register A.
- An interrupt which only occurs once every full moon fires, changing
y
.
- The old value of
y
is stored in x
- yay, this is an atomic instruction!
- Now
x
has the old, outdated value.
Correct real-time behavior would have been to either completely update x
before the interrupt hit, or alternatively update it after the interrupt hit.