Выравнивание памяти (особенно с использованием C) - PullRequest
4 голосов
/ 29 сентября 2011

Если у вас есть структура внутри структуры, скажите:

struct {
    double a;
    struct {
        char *b[20];
        char c;
    }d;
}e;

, структура будет нуждаться в запуске, кратном размеру структуры d или кратном размеру наибольшегочлен d (символ * b [20])?

Ответы [ 2 ]

5 голосов
/ 29 сентября 2011

Структура e будет начинаться с любого выравнивания, необходимого для того, чтобы члены и структура в целом были доступны.

Это выравнивание будет различным для разных реализаций.

Мы знаем, что выравнивание для e будет по крайней мере таким же строгим, как alignmentf для double и по крайней мере таким же строгим, как выравнивание для e.d - - и выравнивание e.d будет, по крайней мере, таким же строгим, как выравнивание для его членов.

Вопреки другим ответам, выравнивание скалярного типа не обязательно совпадает с его размером. Например, возможно, что double может быть 8 байтов, но требует только 4-байтового выравнивания. Выравнивание каждого скалярного типа (целое число, число с плавающей точкой, указатель) по его полному размеру довольно распространено, но оно не универсально.

И обратите внимание, что оптимальное выравнивание может быть более строгим, чем требуемое выравнивание . На x86, насколько я понимаю, процессор может получить доступ к объектам на любой границе байта, но доступ к правильно выровненным объектам более эффективен. (На других процессорах для несогласованного доступа может потребоваться поддержка программного обеспечения.) Компиляторы обычно выравнивают объекты для максимальной эффективности (но могут предоставлять нестандартные расширения для экономии места).

Но выравнивание для типа не может превышать его размер. Например, вы не можете иметь 3-байтовый тип, который требует 4-байтового выравнивания. Массивы не могут иметь разрывы между своими элементами. (В таком случае компилятор, вероятно, дополнит тип до 4 байтов; заполнение будет частью объекта, а не вставляется между объектами.)

4 голосов
/ 29 сентября 2011

Это зависит от компилятора и настроек. В большинстве случаев начнется с гранулярности первого члена, которая в вашем случае sizeof(char*). Обратите внимание, что это не sizeof(char*) * 20, так как это массив, а не нативный тип. Также обратите внимание, что в вашем случае struct e всегда будет начинаться хотя бы с гранулярности sizeof(double), и поэтому struct d будет также.

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