sizeof () ведет себя по-разному между 32-битными и 64-битными процессами

Рассмотрим следующую программу

#include<iostream>

struct SimpleStructure
{
double obj;
};

struct Composite
{
struct SimpleStructure u;
char ch;
};

int main()
{
using namespace std;

cout << "sizeof(double)                 : " << sizeof(double) << endl;
cout << "sizeof(struct SimpleStructure) : " << sizeof(struct SimpleStructure) << endl;
cout << "sizeof(struct Composite)       : " << sizeof(struct Composite) << endl;
return 0;
}

Когда я скомпилирую выше с g++ -m64 <filename>.cppЯ получаю следующий вывод

sizeof(double)                 : 8
sizeof(struct SimpleStructure) : 8
sizeof(struct Composite)       : 16

Но тот же код, когда я компилирую с помощью g++ -m32 <filename>.cppЯ получаю следующий вывод

sizeof(double)                 : 8
sizeof(struct SimpleStructure) : 8
sizeof(struct Composite)       : 12

Почему разница в заполнении в структуре в 32-битном и 64-битном процессах?

-2

Решение

На 32-битной платформе alignof(double) == 4, Увидеть man gcc:

  -malign-double
-mno-align-double
Control whether GCC aligns "double", "long double", and "long long"variables on a two-word boundary or a one-word boundary.  Aligning
"double" variables on a two-word boundary produces code that runs
somewhat faster on a Pentium at the expense of more memory.
On x86-64, -malign-double is enabled by default.

Warning: if you use the -malign-double switch, structures
containing the above types are aligned differently than the
published application binary interface specifications for the
x86-32 and are not binary compatible with structures in code
compiled without that switch.

Размер структуры кратен выравниванию элемента с наибольшим требованием выравнивания. Здесь такой член имеет тип double, так sizeof(struct Composite) == N * alignof(double),

1

Другие решения

Что касается стандарта C, то компилятор может выбрать любое выравнивание. Ниже приведено описание того, как используемые мной компиляторы реализовали выравнивание.

Часто выбирается размер слова (32 бита в 32-битной системе, 64 бита в 64-битной системе), поскольку он обычно является эффективным выбором с точки зрения компромисса между использованием памяти и производительностью на целевой платформе. Обычно доступ к памяти можно получить кусками размером в слово, и в инструкциях процессора предполагается, что данные выровнены, поэтому, если данные выровнены, процессору потребуется получить доступ к 2 частям памяти и сместить данные в выравнивание. Это тратит впустую ценные циклы процессора.

Сущности, меньшие, чем размер слова, выровнены по размеру. Слово размером и более крупные объекты выровнены по границам слова.

Элементы структуры выравниваются отдельно, а затем вся структура дополняется и выравнивается так же, как ее самый большой элемент.

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

Пример:

/* Override the default alignment and pack everything tight. */
#pragma pack(1)
0

Во-первых, размеры целочисленных типов могут варьироваться в зависимости от архитектуры. Здесь есть хороший стол: http://en.cppreference.com/w/cpp/language/types

Во-вторых, указатели имеют разные размеры в зависимости от архитектуры. 32-битные машины имеют 32-битные указатели, а 64-битные машины имеют 64-битные указатели. Если вас интересуют более старые архитектуры, 8-битные машины имели 16-битные указатели, а 16-битные машины имели 32-битные указатели, хотя на 8086 они работали странно.

Наконец, что происходит в вашей структуре, вероятно, выравнивание. По соображениям эффективности переменные выровнены по границам слова, а размер слова может отличаться в разных архитектурах. Смотрите больше информации здесь: http://en.cppreference.com/w/cpp/language/object#Alignment

-1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector