Visual С++ эквивалент GCC __attribute__ ((__packed__))
Для некоторых компиляторов существует спецификатор упаковки для структур, например:
RealView ARM compiler has "__packed"
Gnu C Compiler has "__attribute__ ((__packed__))"
Visual C++ has no equivalent, it only has the "#pragma pack(1)"
Мне нужно что-то, что я могу внести в определение struct.
Любая информация/взлом/предложение? ТИА...
Ответы
Ответ 1
Я не знаю, как это сделать, но вы можете сделать что-то ужасное:
#include "packed.h"
struct Foo { /* members go here */ } PACKED;
#include "endpacked.h"
Затем для MSVC, packing.h:
#define PACKED
#pragma pack(push,1)
endpacked.h
#pragma pack(pop)
#undef PACKED
Для gcc, packed.h:
#define PACKED __attribute__ ((__packed__))
endpacked.h:
#undef PACKED
По сути, упаковка слишком зависима от платформы. Предположим, что ваша упакованная структура имеет в ней 8-битные поля и рассмотрит некоторую систему с 16-разрядным байтом. Он не может иметь структуру, представляющую ваши данные, просто упаковывая - вам нужно будет знать, как 8-битные байты преобразуются в 16-разрядные байты при передаче между этими двумя системами. Структуре на 16-битной машине могут потребоваться бит-поля, и в этом случае вам нужно будет знать, как их реализует.
Итак, если код предназначен, как правило, переносимый, вам просто нужно определить все необходимые структуры, которые вам нужны, в разделе вашего файла заголовка. Вернее, структурируйте свой код, чтобы будущий порт мог это сделать, если он должен.
Ответ 2
Вы можете определить PACK следующим образом для GNU GCC
и MSVC
:
#ifdef __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#endif
#ifdef _MSC_VER
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#endif
И используйте это так:
PACK(struct myStruct
{
int a;
int b;
});
Ответ 3
Я знаю, что этот вопрос уже устарел, но я считаю, что есть лучшее решение, чем те, которые были опубликованы ранее. В конце концов, можно поместить прагму в случае MSVC в строку описания структуры. Учтите следующее:
#ifdef _MSC_VER
# define PACKED_STRUCT(name) \
__pragma(pack(push, 1)) struct name __pragma(pack(pop))
#elif defined(__GNUC__)
# define PACKED_STRUCT(name) struct __attribute__((packed)) name
#endif
Тогда это можно использовать так:
typedef PACKED_STRUCT() { short a; int b } my_struct_t;
PACKED_STRUCT(my_other_struct) { short a; int b };
и т.д.
Ключевым моментом здесь является то, что использование __pragma должно быть только вокруг строки объявления структуры. Это должно включать имя структуры, если оно задано, следовательно, имя является параметром макроса. Конечно, это легко распространить на enum/class, который я оставлю читателю в качестве упражнения!
Тестовая программа на странице документации MSDN Pack полезна для проверки этого.
EDIT
Оказывается, в моем тестировании я использовал компилятор Intel для Windows. При использовании icl.exe этот подход работает без проблем, но с компилятором Microsoft (cl.exe) - нет (протестировано с 2010 и 2013).
Ответ 4
Вы можете сделать это наоборот, поскольку GCC поддерживает связанные с VС++ пакеты. Посмотрите здесь для получения дополнительной информации.
Extract...
Для совместимости с компиляторами Microsoft Windows GCC поддерживает набор директив #pragma
, которые изменяют максимальное выравнивание членов структуры (кроме битовых полей нулевой ширины), союзы и классы впоследствии определяется. Значение n ниже всегда должно быть малая мощность двух и задает новое выравнивание в байтах.
#pragma pack(n)
просто устанавливает новое выравнивание.
#pragma pack()
устанавливает выравнивание по отношению к тому, которое действовало, когда компиляция началась (см. также параметр командной строки -fpack-struct[=<n>]
см. Параметры кода Gen).
#pragma pack(push[,n])
нажимает текущую настройку выравнивания на внутренний стек, а затем необязательно устанавливает новое выравнивание.
#pragma pack(pop)
восстанавливает настройку выравнивания на значение, сохраненное в вершина внутреннего стека (и удаляет эту запись стека).
Обратите внимание, что #pragma pack([n])
не влияет на этот внутренний стек; таким образом, возможно иметь #pragma pack(push)
, за которым следует несколько #pragma pack(n)
экземпляров и финализируется одним #pragma pack(pop)
.
Некоторые цели, например. i386 и powerpc, поддерживайте ms_struct
#pragma
который описывает структуру как документированный __attribute__((ms_struct))
.
#pragma ms_struct on
включает макет для объявленных структур.
#pragma ms_struct off
отключает макет для объявленных структур.
#pragma ms_struct reset
возвращается к макету по умолчанию.
Ответ 5
Другое решение, в зависимости от того, какие компиляторы вам необходимо поддерживать, заключается в том, чтобы заметить, что GCC поддерживал прагмы упаковки в стиле Microsoft с по крайней мере версии 4.0.4 (онлайн-документация доступна на gnu.org для версий 3.4.6 и 4.0.4 - прагмы не описаны в первом и находятся в последнем). Это позволяет вам просто использовать #pragma pack(push,1)
до определения структуры и #pragma pack(pop)
после определения и скомпилировать его в.
Ответ 6
Зачем вам нужно что-то делать в структуре?
Я думаю, что #pragma pack(1)
то же самое, или я чего-то не хватает?
Вы можете сделать это:
struct Foo
{
#pragma pack(push, 1)
int Bar;
#pragma pack(pop)
};
Но это выглядит уродливо.