#pragmapack в C++

зачем нам нужна структура #pragma pack для typedef в C++? В частности, когда вы используете эту структуру в сетевой связи.


person user551008    schedule 22.12.2010    source источник
comment
Вот вся информация, которая вам может понадобиться. Был 1-м в гугле по поисковому запросу pragma pack: msdn.microsoft.com/en-us/library/aa273913%28v=vs.60%29.aspx   -  person bezmax    schedule 22.12.2010
comment
Какое это имеет отношение к объектно-ориентированному программированию?   -  person Jörgen Sigvardsson    schedule 22.12.2010


Ответы (4)


#pragma pack управляет выравниванием членов структуры. Обычное значение по умолчанию — 8, что гарантирует, что элементы длиной до 8 байт будут выровнены по адресу, кратному их размеру. Например, двойной или 64-битный указатель. Чтение или запись неправильно выровненного двойника может быть довольно дорогим, обычно в три раза медленнее, если он выходит за границу строки кэша ЦП. Это выравнивание может создать неиспользуемое пространство между элементами, называемое заполнением.

Такое выравнивание часто не подходит для сетевых фреймов, они, как правило, плотно упакованы без каких-либо отступов, #pragma pack(push, 1)

person Hans Passant    schedule 22.12.2010
comment
+1: Еще один момент: если структура не упакована и вы хотите построить контрольную сумму (CRC), это становится трудным, потому что вам нужно получить доступ к каждому члену структуры, тогда как с упаковкой 1 вы можете просто получить доступ ко всем байтам структура. - person ur.; 22.12.2010

Директива пакета #pragma изменяет текущее правило выравнивания только для членов структур, объявления которых следуют за директивой. Он не влияет на выравнивание структуры напрямую, но, влияя на выравнивание элементов структуры, может влиять на выравнивание всей структуры в соответствии с правилом выравнивания.

person user551008    schedule 22.12.2010

Если вам просто нужно, чтобы две системы с одинаковыми настройками общались друг с другом (тест,...), вы можете отправлять структуры, при условии, что они представляют собой просто POD (обычные старые данные) (указатели, виртуальные таблицы, std::strings.. . нельзя использовать). Так что пакет не нужен.

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

person stefaanv    schedule 22.12.2010

Компиляторы будут «дополнять» поля и подполя структуры, т. е. организовывать их в памяти пустыми участками памяти, которые ничего не содержат посередине. Это делается для повышения эффективности, как объясняет ответ Ханса Пассана.

Различные настройки компилятора/цели/оптимизации могут по-разному заполняться, преобразовывая одинаковые «логические» структуры в неодинаковые представления памяти, поэтому, если две взаимодействующие машины передают структуру между собой, они могут не понять друг друга.

#pragma pack — это ваш способ ограничить свободу компилятора.

#pragma pack(push, 1) приказывает компилятору вообще не дополнять. Если вы сделаете это с двумя идентичными структурами, определенными в разных кодах, они будут одинаково представлены в памяти. Затем вы можете безопасно отправлять содержимое структуры в одном приложении через какой-либо протокол, используя указатель и sizeof(), получать его на другой стороне и записывать прямо над идентичной структурой, также используя указатель и sizeof().

person Emilio M Bumachar    schedule 22.12.2010