Почему sizeof отличается в Linux и VS 32-битного процесса?даже с "#pragma pack" и "-fpack-struct" - PullRequest
0 голосов
/ 01 февраля 2019
#include "stdio.h"

#pragma pack(8)
struct testSize {
    int a;  //size 4, alignment 8
    double b;//size 8, alignment 8
};
#pragma pack()

int main(int argc, char** argv)
{
    printf("sizeof testSize %d \n", sizeof(struct testSize));
    printf("sizeof int %d , sizeof double %d\n", sizeof(int), sizeof(double));

    return 0;
}

Максимальное выравнивание структуры по умолчанию равно 8, а также мы можем установить #pragma pack(8) или -fpack-struct=8.Но в 32-битном процессе, скомпилированном с помощью gcc, он не работает.

В Linux (32):

$ gcc -m32 -fpack-struct=8 -o TestSize TestSize.c
$ ./TestSize
sizeof testSize 12
sizeof int 4 , sizeof double 8

В VS (x86):

sizeof testSize 16
sizeof int 4 , sizeof double 8

В linux выравнивание выглядит как 4, а не 8. Из документа это «Для совместимости с компиляторами Microsoft Windows».

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Документация и наблюдаемое поведение GCC согласуются друг с другом.

Документы GCC :

Для совместимости с компиляторами Microsoft Windows GCC поддерживаетнабор директив #pragma, которые изменяют максимальное выравнивание элементов структур

[...]

# pragma pack (n) просто устанавливает новое [максимальное] выравнивание

Полученный размер структуры показывает, что GCC в Linux выравнивает double по четырехбайтовой (или менее) границе.Четыре меньше 8.


Документация и наблюдаемое поведение VS соответствуют друг другу.

Документы VS :

Указывает выравнивание упаковки для элементов структуры, объединения и класса.

[...]

n [...] Выравнивание элемента будет на границе, котораякратен n или кратен размеру элемента, в зависимости от того, что меньше.

Размер double равен 8, а указанное максимальное выравнивание равно 8.Размер структуры показывает, что VS в Windows выравнивает double на 8-байтовой границе, как и должно быть.


В Linux выравнивание выглядит как 4, а не 8. Изdoc, это «Для совместимости с компиляторами Microsoft Windows».

Оба компилятора принимают вашу прагму.Это не имеет практического влияния ни на один из них.Это совместимость исходного кода с прагмой.

То, что правила выравнивания по умолчанию для двух компиляторов различаются, может рассматриваться как несовместимость, но это не проблема прагмы.И в этом случае вы можете использовать прагму, чтобы получить одинаковое (более слабое) выравнивание обеих структур, указав максимальное выравнивание 4. Или вы сможете получить более сильное выравнивание с GCC на x86 Linux с помощью опции компилятора -malign-double.

Но хорошо заметьте, что, посмотрев на VS в Windows и GCC в Linux , вы сравниваете яблоки и апельсины.На этих платформах не учитывается бинарная совместимость.Попробуйте провести эксперимент с Windows GCC, например MinGW.Сейчас я не могу тестировать, но я ожидаю, что GCC в Windows будет соответствовать соглашениям о выравнивании Windows по умолчанию, и что pragma pack будет влиять на компоновку точно так же, как и в GCC / Windows.на VS / Windows.

0 голосов
/ 01 февраля 2019

На странице GCC, на которую вы ссылаетесь, написано, что прагма "меняет выравнивание максимум ".Вполне возможно, что указанные вами 8 байты игнорируются в пользу меньшего значения по умолчанию из 4 в вашей цели компиляции.

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

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