C 64-битное выравнивание указателя - PullRequest
11 голосов
/ 24 марта 2010

Указатели в 64-битной системе все еще выровнены по 4 байта (аналогично двойному в 32-битной системе)? Или они отмечают, что 8 байтов выровнены?

Например, в 64-битной системе насколько велика следующая структура данных:

struct a {
    void* ptr;
    char myChar;
}

Будет ли указатель выровнен на 8 байт, что приведет к заполнению символа 7 байтами (всего = 8 + 8 = 16)? Или указатель будет выровнен на 4 байта (4 байта + 4 байта), что приведет к заполнению 3 байтами (всего = 4 + 4 + 4 = 12)?

Спасибо, Райан

Ответы [ 5 ]

6 голосов
/ 24 марта 2010

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

Однако, если вы используете настройки по умолчанию, на большинстве (если не на всех) компиляторах структура должна в итоге составлять 16 байтов. Причина в том, что компьютеры читают блок данных с размером его собственного размера слова (который составляет 8 байтов в 64-битной системе). Если бы он дополнял смещение до 4 байтов, следующая структура не была бы должным образом дополнена до 64-битной границы. Например, в случае arr [2], второй элемент массива будет начинаться со смещением в 12 байтов, которое не находится на собственной границе байта машины.

6 голосов
/ 24 марта 2010

Я не думаю, что вы можете положиться на какие-то жесткие правила.Я думаю, что это функция используемого вами компилятора и выбранных вами опций компиляции.

Лучше всего вам написать программу, которая проверяет это и выдает заголовочный файл, который кодирует правила выравнивания как #define s.,Вы также можете просто рассчитать, что вас интересует, прямо в макросах.

3 голосов
/ 24 марта 2010

Обычно в 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-битных систем.

1 голос
/ 24 марта 2010

Стандарт языка не делает никаких заявлений о заполнении. Правила выравнивания зависят от платформы (т. Е. Вы должны выровнять по-разному, например, на процессоре PowerPC, чем на процессоре x86_64), и они определяются реализацией, что означает, что ваш компилятор может выполнять любые действия (и может изменить это поведение другой командой опции или после обновления версии).

Я твердо верю, что любая рекомендация в духе "это обычно то или другое" вводит в заблуждение и, возможно, опасна.

  1. Вы можете написать тестовую программу, которая выполнит пару операторов sizeof() и / или offsetof() и напишет для вас заголовок, содержащий несколько #define с указанием используемых заполнителей.

  2. Вы можете использовать autoconf, чтобы сделать это для вас.

  3. По крайней мере, вы должны добавить операторы assert( sizeof( ... ) ) в начале вашей функции main(), чтобы получать информацию, когда ваши предположения неверны.

0 голосов
/ 24 марта 2010

Вам необходимо обратиться к документации по конкретному ABI, который вас интересует. Например, вот Приложение архитектуры V ABI x86-64 - на странице 12 вы можете увидеть указатели на это ABI выровнены по 8 байтов (так что да, структура, которую вы показываете, будет дополнена до 16 байтов).

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