Начинающим да и продолжающим программистам порой непонятно, почему в некоторых случаях размер структуры может быть больше, чем суммарный размер входящих в нее членов. Например:
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 байт
Отправить комментарий