This is very architecture dependent, and you don't specify what type of system you're on.
However, assuming
char
: 1 byte size, no alignment
short
: 2 byte size, aligned to 2 byte boundaries
int
: 4 byte size, aligned to 4 byte boundaries
double
: 8 byte size, aligned to 8 byte boundaries
this is easily explained.
+------+ +------+
| char | 0 | char |
+------+ +------+
| | 1 | |
+------+ | |
| | 2 | |
| short| | |
| | 3 | |
+------+ | |
| | 4 | |
| | | |
| | 5 | |
| int | | |
| | 6 | |
| | | |
| | 7 | |
+------+ +------+
| | 8 | |
| | | |
| | 9 | |
| | | |
| | 10 | |
| | | |
| | 11 | |
|double| |double|
| | 12 | |
| | | |
| | 13 | |
| | | |
| | 14 | |
| | | |
| | 15 | |
+------+ +------+
16 | |
| |
17 | |
| int |
18 | |
| |
19 | |
+------+
20 | |
| short|
21 | |
+------+
22 | |
| |
23 | |
+------+
There is empty space (called padding) in your structures, because certain data structures must fall on certain byte boundaries.
Note that the struct as a whole must be aligned to 8 byte boundaries to maintain the alignment of its members; that's why there's extra padding on the tail of the second version.