До сегодняшнего дня я использовал следующую технику для упаковки структур:
#pragma pack(push,1)
struct mystruct
{
char a1;
char a2;
int a3;
}
#pragma pack(pop)
mystruct mydata()
{
mystruct ms;
ms.a1='a';
ms.a2='b';
ms.a3=12;
return ms;
}
и предположил, что ms упакован как 1, но сегодня кто-то сказал мне, что в вышеприведенном определении ms упакован как 4, так как pack не влияет на определение, но на объявление. http://msdn.microsoft.com/en-us/library/aa273913%28v=vs.60%29.aspx
Может кто-нибудь уточнить, было ли то, что я сделал, правильно или нет?
Стандарт определяет § 3.1 / 2
Декларация является определением если она не объявляет функцию без указания тела функции (8.4), она
содержит спецификатор extern (7.1.1) или спецификацию связи25 (7.5), а также инициализатор и тело функции,
он объявляет член статических данных в определении класса (9.2, 9.4), это объявление имени класса (9.1), это
непрозрачное-enum-объявление (7.2), это шаблон-параметр (14.1), это объявление параметра (8.3.5) в
декларатор функции, который не является декларатором определения функции, или это объявление typedef (7.1.3),
декларация псевдонимов (7.1.3), декларация использования (7.3.3), декларация static_assert (раздел 7), объявление атрибута
(Пункт 7), пустое объявление (пункт 7) или директива об использовании (7.3.4).
таким образом, у вас есть определение структуры, как вы правильно заметили, но это также объявление, поэтому случай
пакет не влияет на определения
применяется, но не для декларации. На самом деле MSVC и GCC / Clang правильно упаковать выше с 1
struct mystruct_not_packed
{
char a1;
char a2;
int a3;
};
#pragma pack(push,1)
struct mystruct
{
char a1;
char a2;
int a3;
};
mystruct_not_packed object; // This doesn't apply
#pragma pack(pop)
int main(int argc, char *argv[])
{
std::cout << sizeof(mystruct) << std::endl; // 6
std::cout << sizeof(mystruct_not_packed) << std::endl; // 8
std::cout << sizeof(object) << std::endl; // 8
}
(протестировано с MSVC2013U4)
Фраза «Прагма не влияет на определения» означает, что если вы напишите
struct mystruct
{
char a1;
char a2;
int a3;
};
#pragma pack(push,1)
mystruct ms;
#pragma pack(pop)
Это не повлияет на упаковку ms
,
Но в вашем примере ms
будет упаковано в 1, вот и весь смысл pragma pack
,
(Результаты MSVC 2013 8 6
на этот код, а также лязг и gcc на колиру)