Предположим, у вас есть структура.
struct S {
short a;
int b;
char c, d;
};
Без выравнивания он будет размещен в памяти следующим образом (при условии 32-битной архитектуры):
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
Проблема в том, что на некоторых архитектурах ЦП инструкция по загрузке 4-байтового целого числа из памяти работает только на границах слов. Таким образом, ваша программа должна получать каждую половину b
с отдельными инструкциями.
Но если память выложена как:
0 1 2 3 4 5 6 7 8 9 A B
|a|a| | |b|b|b|b|c|d| | |
| | | |
Тогда доступ к b
становится простым. (Недостатком является то, что из-за байтов заполнения требуется больше памяти.)
Различные типы данных имеют разные требования к выравниванию. Обычно char
выравнивается по 1 байту, short
- по 2 байта, а 4-байтовые типы (int
, float
и указатели в 32-разрядных системах) - 4 байта выровнены.
malloc
требуется стандартом C для возврата указателя, правильно выровненного для любого типа данных.
glibc malloc
на x86-64 возвращает 16-байтовые совмещенные указатели.