Подтвердить что ты не робот

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.

Любая информация/взлом/предложение? ТИА...

4b9b3361

Ответ 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)
};

Но это выглядит уродливо.