Я хотел бы знать, почему мы должны взять для размера выравнивания структуры размер выравнивания, равный наибольшему размеру члена в структуре.
Пример:
struct MixedData
{
char Data1;
short Data2;
int Data3;
char Data4;
};
Если мы берем наибольший член (int Data3)
, выравнивание равно 4 байтам, так что нам нужно сделать:
struct MixedData /* After compilation in 32-bit x86 machine */
{
char Data1; /* 1 byte */
char Padding1[1]; /* 1 byte for the following 'short' to be aligned on a 2 byte boundary
assuming that the address where structure begins is an even number */
short Data2; /* 2 bytes */
int Data3; /* 4 bytes - largest structure member */
char Data4; /* 1 byte */
char Padding2[3]; /* 3 bytes to make total size of the structure 12 bytes */
};
Но почему у меня нет, после char Data1
, char Padding1[3]
поэтому short Data2
начинается с adress(Data1) + 4
вместо char Data1[1]
?
И, с той же логикой, почему у меня нет short Padding3[1]
после short Data2
?
Другой вопрос: если я на 64-битном процессоре, я должен использовать выравнивание по 8 байт, поэтому я должен установить следующее:
struct MixedData /* After compilation in 64-bit x86_64 machine */
{
char Data1; /* 1 byte */
char Padding1[7]; /* 7 bytes */
int Data3;
int Padding2[1]/* 4 bytes */
char Data4;
char Padding3[7]; /* 7 bytes to make total size of the structure 24 bytes */
};
?
поэтому общий размер 24 байта кратен 8 байтам?
OVERALL-выравнивание структуры должно соответствовать элементу с наибольшим требованием выравнивания. Это необходимо для обеспечения того, чтобы, например, массив структур всегда выравнивался. Если у вас этого нет, размер struct { int x; char c; };
struct { int x; char c; };
будет иметь первый элемент, выровненный, но следующие три будут иметь x
unaligned.
Часто можно убедить компилятор генерировать "упакованную" структуру данных (без добавления выравнивания) и использовать ее для получения упакованного массива, но это плохая идея использовать это во всех, кроме очень особых случаях, потому что в лучшем случае это медленнее, в худшем случае это приводит к остановке выполнения из-за "неувязки доступа" в процессоре.
Если размер int
равен четырем байтам [это для всех компиляторов, о которых я знаю - long
- это 4 или 8 байт, зависит от компилятора), как на 32-, так и на 64-битной (по крайней мере, x86) будет выровнять по 4 байта.
Если вы хотите иметь 7-байтовый "пробел" в структуре, это будет работать:
struct X {
char c;
uint64_t x;
};
что, конечно же, имело бы:
struct X {
char c;
char padding[7];
uint64_t x;
};