Начинающим да и продолжающим программистам порой непонятно, почему в некоторых случаях размер структуры может быть больше, чем суммарный размер входящих в нее членов. Например:
struct Test { char var1; // 1 байт short var2; // 2 байта };Как видно, суммарный размер структуры должен быть равен 3 байтам, на деле же оказывается вовсе не 3, а 4 байта.
Именно такой результат возвратит нам sizeof(Test). Все дело в выравнивание, которое осуществляет компилятор.
Т.е. данные помещаются по адресам, кратным размерам своих типов - 2-байтовые данные буду находятся по адресу, кратному 2, 4-байтные - по адресу, кратному 4 и т.д. (выравнивание по умолчанию)
Выравнивание нужно, потому что с выровненными данными процессор работает более эффективно. Если процессор обращается к невыровненным данным, то сначала он считывает одну часть данных, затем считывает другую часть, после этого компонует и получает исходные данные. Все это сокращает производительность.
Для выравнивания между данными помещаются специальные байты отступа (padding)
Рассмотрим примеры (ОС Windows).
struct Test { unsigned char var1; unsigned char var2; unsigned char var3; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
char | char | char | ... |
В итоге суммарный размер равен 3 байта.
Другой пример:
struct Test { unsigned char var1; unsigned short var2; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
char | P | short | ... |
struct Test { unsigned short var1; unsigned char var2; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
short | char | P | ... |
Допустим у нас есть такая структура:
struct Test { unsigned int var1; unsigned char var2; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
int | char | P | P | P | ... |
Если имеется структура
struct Test { unsigned int var1; unsigned short var2; unsigned char var3; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
int | short | char | P | ... |
Аналогично рассмотрим структуру вида
struct Test { double var1; unsigned int var2; unsigned short var3; unsigned char var4; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ||||||
double | int | short | char | P | ... |
Представим такую ситуацию:
struct Test { unsigned short var1; unsigned char var2; double var3; };
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
short | char | P | P | P | P | P | double | ... |
ВНИМАНИЕ! Данные результаты получены при опции компилятора
Struct member alignment = Default;
Для значений /zp1, /zp2, zp[n] результаты будут отличны от полученных.
2 комментария :
Руслан, а что будет с массивами внутри структур?
Масиивы - это подряд идущие элементы одного и того же типа. Например если рассматривать структуру вида
struct A
{
int iAr[2];
char chAr[2];
};
то ее можно свести к такому виду
struct A
{
int iVal1;
int iVal2;
char chVal1;
char chVal2;
};
Считаем: 4(int) + 4(int) + 1(char) + 1(char) + 2(padding до 4) = 12 байт
Отправить комментарий