При использовании структур, включающих поля различных типов, следует быть очень внимательным и четко осознавать, как структура будет располагаться в памяти. В противном случае это может привести к трудновыявляемым ошибкам.
Предположим, объявлена такая структура:
struct bug_t {
int a;
long long b;
int c;
};
Размер структуры: sizeof(struct bug_t) = 24 байта, причем sizeof(int)=4, sizeof(long long) = 8. Итого должно быть 16. Как же получается 24?
А получается, что 8 байт уходят на выравнивание. В памяти структура будет располагаться следующим образом:
1) Поле "а" (4 байта)
2) 4 байта дополнения (!). Они необходимы для выравнивания следующего 8-байтового поля.
3) 8 байт поля "b" (long long)
4) 4 байта поля "с"
5) 4 байта дополнения (!). А зачем же нужны эти 4 байта? Все дело в том, что выравнивание структуры должно быть равно выравниванию ее максимального элемента, т.е. long long.
Для того, чтобы память не тратилась на выравнивание можно, например, переставить элементы в структуре местами:
struct bug_t {
int a;
int c;
long long b;
};
В этом случае все элементы будут располагаться в памяти подряд.
В заключение следует заметить, что подобным образом выравнивание будет выполняться не для всех процессоров (но для MIPS и PowerPC это так) и компиляторов. Во многих компиляторах есть специальные опции компиляции и макросы #pragma, позволяющие управлять выравниванием.