Всегда ли одинаковый эффект #pragma pack(16) и #pragma pack(8)?
Я пытаюсь выровнять элементы данных с помощью #pragma pack (n)
, Возьмите следующее в качестве примера:
#include <iostream>
using namespace std;
#pragma pack(8) // or (16)
struct A
{
int a;
char b;
char c;
char d;
char e;
char f;
double g;
};
int main()
{
cout << sizeof(A) << endl;
return 0;
}
Оба распечатают 24
за #pragma pack(8)
а также #pragma pack(16)
, Я могу понять результат для n=8
с выравниванием данных, насколько я понимаю, следующим образом:
Bytes: |1 2 3 4|5|6|7|8|9|10 11 12 13 14 15 16|17 18 19 20 21 22 23 24|
Data: |a |b|c|d|e|f|padding |g |
Но я не могу понять, почему результат все еще 24
за n=16
, Я также пробовал другие примеры, все они, кажется, дают тот же результат для n=8
а также n=16
, Может кто-нибудь объяснить почему? Выровнены ли элементы данных так же, как n=8
?
PS: Проверено в VS2010 под Win-x64.
3 ответа
Со страницы, на которую вы ссылаетесь:
Выравнивание элемента будет на границе, кратной n или кратной размеру элемента, в зависимости от того, что меньше.
Для каждого элемента требуется минимальное выравнивание между оптимальным выравниванием элемента и значением пакета. Члены в вашем примере выровнены точно так же, независимо от pack(8)
а также pack(16)
потому что оптимальное выравнивание типов все меньше 16.
Если у вас был элемент, для которого требовалось 16-байтовое выравнивание, например __m128
, вы сможете найти разные результаты.
За pack
значить много, рассматриваемая структура должна содержать член, по крайней мере, такой же большой, как N
вы указываете на прагму. Например:
#include <iostream>
using namespace std;
#pragma pack(push)
#pragma pack(1)
struct A
{
char a;
double b;
};
#pragma pack(8)
struct B
{
char a;
double b;
};
#pragma pack(pop)
int main()
{
cout << sizeof(A) << "\n" << sizeof(B) << endl;
return 0;
}
На моем компьютере это печатает:
9
16
... что я считаю довольно типичным (по крайней мере, для машин, которые принимают pragma pack
на первом месте).
Поскольку pack указывает максимальное выравнивание, используемое при необходимости. Значения, меньшие 16 байтов, все равно будут выровнены с меньшими значениями, потому что нет никакой выгоды в выравнивании их с большими значениями. Поэтому 32-разрядное целое число все еще выровнено до 4 байтов. Двойник выравнивается до 8 байтов. Так что вы, вероятно, увидите разницу при переключении между 4 и 8.