Выравнивание переменных в памяти (краткая история).
В прошлом компьютеры имели 8 бит данных. Это означает, что каждый тактовый цикл может обрабатывать 8 бит информации. Что было хорошо тогда.
Затем появились 16-битные компьютеры. Из-за обратной совместимости и других проблем 8-битный байт был сохранен, и было введено 16-битное слово. Каждое слово было 2 байта. И каждый тактовый цикл может обрабатывать 16 бит информации. Но это поставило небольшую проблему.
Давайте посмотрим на карту памяти:
+----+
|0000|
|0001|
+----+
|0002|
|0003|
+----+
|0004|
|0005|
+----+
| .. |
На каждом адресе имеется байт, доступ к которому можно получить индивидуально.
Но слова могут быть получены только по четным адресам. Поэтому, если мы читаем слово в 0000, мы читаем байты в 0000 и 0001. Но если мы хотим прочитать слово в позиции 0001, нам нужно два доступа для чтения. Сначала 0000,0001, а затем 0002,0003, и мы оставляем только 0001,0002.
Конечно, это заняло дополнительное время, и это не было оценено. Вот почему они изобрели выравнивание. Таким образом, мы храним переменные слова на границах слова и байтовые переменные на границах байта.
Например, если у нас есть структура с байтовым полем (B) и словом (W) (и очень наивный компилятор), мы получим следующее:
+----+
|0000| B
|0001| W
+----+
|0002| W
|0003|
+----+
Что не весело. Но при использовании выравнивания слов мы находим:
+----+
|0000| B
|0001| -
+----+
|0002| W
|0003| W
+----+
Здесь память жертвуется ради скорости доступа.
Вы можете себе представить, что при использовании двойного слова (4 байта) или четырехзначного слова (8 байтов) это еще важнее. Вот почему с большинством современных компиляторов вы можете выбирать, какое выравнивание вы используете при компиляции программы.