Выравнивание структуры может привести к потере памяти? - PullRequest
2 голосов
/ 11 февраля 2020

Теперь у меня есть структура st, которая содержит другую структуру внутри:

struct st2 {
    char b = 2;
    long c = 3;
};

struct st {
    char a = 1;
    st2 mySt;
    int d = 4;
    char e = 5;
};

Когда я проверяю эту структуру st в памяти, она выглядит следующим образом:

0x7fffffffdce0: 0x01    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffdce8: 0x02    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffdcf0: 0x03    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffdcf8: 0x04    0x00    0x00    0x00    0x05    0x00    0x00    0x00

Кажется что первый символ mySt выровнен по 8 (в x64 я думаю, что он использует размер struct st2, а #pragma pack по умолчанию равен 8).

Однако, если вы позволите мне разработать компилятор, я разберу mySt и рассмотрю каждый тип basi c mySt как st, поэтому между членами a и b не должно быть заполнения:

struct st {
    char a = 1;
    char b = 2;  // unwind mySt
    long c = 3;  // unwind mySt
    int d = 4;
    char e = 5;
};

// Now the char a and b can storage in just one qword, by unwinding the sub structure.
0x7fffffffdcf0: 0x01    0x02    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffdcf8: 0x03    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffdd00: 0x04    0x00    0x00    0x00    0x05    0x00    0x00    0x00

Итак, вот вопрос: почему компилятор не выровнялся с типом basi c в каждой подструктуре, а выровнялся по размеру всей подструктуры? Разве это не пустая трата памяти?

1 Ответ

8 голосов
/ 11 февраля 2020

Все экземпляры st2 имеют одинаковое расположение. Место хранения объекта может не повлиять на этот макет. То, является ли объект членом или нет, может не повлиять на этот макет. Компилятор не может просто выбрать один из элементов mySt и сохранить его вне объекта.

Рассмотреть возможность передачи st2 в функцию:

void some_function(st2&);

Эта функция не может знать, где этот объект исходит от. Но он должен иметь возможность доступа к членам объекта. Расположение объекта должно быть известно во время компиляции. Если один экземпляр st2 будет иметь разную компоновку из другого, откуда будет знать функция?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...