Я объявил в структуре только члены типа char
.
#include struct st { char c1; char c2; char c3; char c4; char c5; }; int main() { struct st s; printf("%zu\n", sizeof(s)); return 0; }
Выход: [ Live Demo ]
5
Итак, почему в структуре нет char
элементов только для членов типа char
?
Прокладка в структуре существует (в основном) для обеспечения того, чтобы отдельные члены были привязаны к их основному требованию выравнивания , то есть ( C11 3.2p1 ):
требование о том, чтобы объекты определенного типа располагались на границах хранилища с адресами, которые являются частями кратного байтового адреса
Прокладка в середине и в конце структуры используется для обеспечения того, что даже в пределах массива этих структур каждый элемент будет по-прежнему выровнен в соответствии с их требованиями к выравниванию. C11 6.2.8p1 :
Полные типы объектов имеют требования к выравниванию, которые ограничивают адреса, по которым могут быть выделены объекты этого типа. Выравнивание представляет собой целочисленное значение, определяемое реализацией, представляющее количество байтов между последовательными адресами, по которым может быть выделен данный объект. Тип объекта налагает требование выравнивания для каждого объекта такого типа: более строгое выравнивание можно запросить с помощью ключевого слова _Alignas.
Теперь требование выравнивания для каждого другого типа определяется реализацией, но подразумевается одно: поскольку требование выравнивания выражается в size_t
; sizeof (char)
равен 1, а указатели на типы символов могут использоваться для адресации каждого отдельного символа в других типах, тип символа не может иметь фундаментальное требование выравнивания больше 1. Неожиданно это не указано в стандарте C вообще ; у этого просто есть эта неопределенная формулировка ( C11 6.2.8p6 ):
Типы
char
,signed char
иunsigned char
должны иметь самое слабое требование к выравниванию.
Поскольку выравнивание char
не более 1, компилятору не нужно добавлять никаких дополнений, потому что даже если структура имеет ровно 5 байтов, то даже в массиве с некоторыми структурами, начинающимися с нечетного адреса, каждый из элементов этих структур все равно будут правильно выровнены.
Отступы должны обеспечивать соблюдение требований выравнивания . Утверждается, что член выравнивается (по его размеру), если он расположен по адресу, который делится на его размер.
В вашем примере нет необходимости заполнить, так как все члены st
структуры уже выровнены по своему размеру, то есть: адрес каждого элемента st
уже делится на его размер. Все члены имеют тип char
и размер char
равен 1 . Если размер участника равен 1 , этот член всегда выровнен по своему размеру, так как любой адрес делится на 1 .
Некоторые типы, когда они правильно выровнены, имеют лучшую производительность / стабильность и т. Д. Если для переменной такого типа есть другие переменные, которые делают его исходное положение «не выровненным», компилятор может принять решение добавить дополнение, чтобы выравнивание проходило хорошо , Это все необязательно, и, конечно, нет необходимости, когда у вас есть байты ( char
).
Скорее всего, вы заметите прописку, если вы создадите такую структуру:
struct pad{ int8_t a; int64_t b; }; assert(sizeof(struct pad) == 16);
чей формат памяти должен выглядеть так:
|---|-------|---------| | 1 | 7 | 8 | |---|-------|---------| byte|padding|64-bit int
Опять же, нет необходимости выровнять байты, поскольку они являются минимальной единицей хранения.