If a struct is declared like this:
struct foo {
whatever_type_t first_member;
// ...
};
then an array of this type can also be declared: struct foo farray[42];
A conforming ISO C implementation has to ensure that farray[1].first_member, and farray[2].first_member, and so on, are all allocated such that they meet the alignment requirements fro whatever_type_t. It cannot be that farray[0].first_member is accessible, but farray[1].first_member throws an alignment exception or whatever. Programmers should not have to do anything to ensure this.So, if necessary, padding is added at the end of struct foo to make this alignment happen.
In practice, compilers add the padding even if it's not required for at least two reasons: performance (misaligned accesses, though supported, may be slow) and compatibility (having the structure look the same across multiple architectures supported by the same compiler, at most modulo byte order).
> You should also be using the fixed-width numeric types.
I'm not aware that C provides any other, currently. Though you can simulate them with libraries, of course.