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 байтов).