Вы можете увидеть, что происходит более четко, с помощью макроса offsetof()
:
#include <iostream>
#include <cstddef>
using namespace std;
struct test
{
int i;
double h;
int j;
};
int main()
{
test te;
te.i = 5;
te.h = 6.5;
te.j = 10;
cout << "size of an int: " << sizeof(int) << endl; // Should be 4
cout << "size of a double: " << sizeof(double) << endl; // Should be 8
cout << "size of test: " << sizeof(test) << endl; // Should be 24 (word size of 8 for double)
cout << "i: size = " << sizeof te.i << ", offset = " << offsetof(test, i) << endl;
cout << "h: size = " << sizeof te.h << ", offset = " << offsetof(test, h) << endl;
cout << "j: size = " << sizeof te.j << ", offset = " << offsetof(test, j) << endl;
return 0;
}
В моей системе (x86) я получаю следующий вывод:
size of an int: 4
size of a double: 8
size of test: 16
i: size = 4, offset = 0
h: size = 8, offset = 4
j: size = 4, offset = 12
В другой системе (SPARC) я получаю:
size of an int: 4
size of a double: 8
size of test: 24
i: size = 4, offset = 0
h: size = 8, offset = 8
j: size = 4, offset = 16
Компилятор вставляет байты заполнения между членами структуры, чтобы гарантировать правильное выравнивание каждого элемента. Как видите, требования к выравниванию варьируются от системы к системе; в одной системе (x86) double
равен 8 байтам, но требуется только 4-байтовое выравнивание, а в другой системе (SPARC) double
равен 8 байтам и требует 8-байтовое выравнивание.
Заполнение также может быть добавлено в конце структуры, чтобы гарантировать, что все выровнено правильно, когда у вас есть массив типа структуры. Например, в SPARC компиляция добавляет 4 байта pf-заполнения в конце структуры.
Язык гарантирует, что первый объявленный член будет иметь смещение 0, и что члены располагаются в порядке, в котором они объявлены. (По крайней мере, это так для простых структур; метаданные C ++ могут усложнить ситуацию.)