C 64-разрядное выравнивание указателя
Являются ли указатели на 64-битной системе еще 4 байтами выровнены (аналогично удвоению в 32-битной системе)? Или они отмечают, что 8 байт выровнены?
Например, в 64-битной системе, насколько велика следующая структура данных:
struct a {
void* ptr;
char myChar;
}
Будет ли указатель выровнен по 8 байт, вызывая 7 байтов заполнения для символа (total = 8 + 8 = 16)? Или бы указатель был выровнен по 4 байт (4 байта + 4 байта), вызывая 3 байта заполнения (total = 4 + 4 + 4 = 12)?
Спасибо,
Райан
Ответы
Ответ 1
Выравнивание и упаковка данных являются специфичными для реализации и могут быть обычно изменены из настроек компилятора (или даже с помощью прагм).
Однако если вы используете настройки по умолчанию, то для большинства (если не для всех) компиляторов структура должна составлять всего 16 байт. Причина в том, что компьютеры читают кусок данных с размером своего собственного размера слова (который составляет 8 байтов в 64-битной системе). Если бы это было место для 4 байтовых смещений, следующая структура не была бы должным образом дополнена до 64-битной границы. Например, в случае arr [2], второй элемент массива должен начинаться с 12-байтового смещения, которое не находится на нативной байтовой границе машины.
Ответ 2
Я не думаю, что вы можете полагаться на любые жесткие правила. Я думаю, что это функция компилятора, который вы используете, и варианты компиляции, которые вы выбираете.
Лучше всего написать программу, которая проверяет это и выдает файл заголовка, который кодирует правила выравнивания как #define
s. Вы также можете просто рассчитать то, что вас интересует прямо в макросах.
Ответ 3
Обычно в 64-битной системе:
struct a {
void* ptr; // size is 8 bytes, alignment is 8
char myChar; // size is 1 byte, alignment is 1
// padding of 7 bytes so array elements will be properly aligned
}
Общий размер 16 байт.
Но это вся реализация определена - я просто даю пример, который может быть правдой для многих (большинство?) 64-битных систем.
Ответ 4
В стандарте языка нет утверждений о заполнении. Правила выравнивания специфичны для платформы (т.е. Вы должны по-разному согласовывать, например, с процессором PowerPC, чем с процессором x86_64), и они определяются реализацией, что означает, что ваш компилятор может делать все, что работает (и может изменить это поведение с помощью другой команды -line или после обновления версии).
Я твердо верю, что любая рекомендация по принципу "это обычно то или это" вводит в заблуждение и, возможно, опасна.
-
Вы можете написать тестовую программу, которая выполняет несколько операторов sizeof()
и/или offsetof()
и записывает заголовок для вас, содержащий некоторые #define
, в которых указаны используемые paddings.
-
Вы можете использовать autoconf
для этого.
-
По крайней мере, вы должны добавить инструкции assert( sizeof( ... ) )
в начале вашей функции main()
, чтобы вы узнали, когда ваши предположения ошибочны.
Ответ 5
Вам нужно будет проконсультироваться с документацией для конкретного интересующего вас ABI. Например, здесь дополнение к архитектуре VIVA x86-64 System - вы можете видеть на странице 12, что указатели на этом ABI выровнены по 8 байт (так что да, структура, которую вы показываете, будет дополнена до 16 байтов).