Как вы сказали, C++Builder не поддерживает операторы препроцессора внутри макросов. Это задокументировано на сайте Embarcadero:
#define (C++)
После каждого отдельного расширения макроса выполняется дальнейшее сканирование вновь расширенного текста. Это допускает возможность вложенных макросов: расширенный текст может содержать идентификаторы макросов, подлежащие замене. Однако, если макрос превращается в нечто, похожее на директиву препроцессора, эта директива не будет распознана препроцессором.
Причина этого в том, что символ #
внутри макроса зарезервирован для оператора преобразования строк препроцессора.
Некоторые компиляторы, в том числе MSVC, обходят это ограничение с помощью расширения компилятора __pragma()
или расширения C99/C++x0 _Pragma()
. Компилятор Windows 32bit C++Builder не поддерживает ни один из них. Однако его компиляторы Windows 64bit и мобильные (все они основаны на clang и поддерживают C++11) DO поддерживают оба из них. Таким образом, вы можете добавить поддержку этих компиляторов в макросы следующим образом:
#if defined(__BORLANDC__)
#if defined(__clang__)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#else
#error Cannot define PACKED macros for this compiler
#endif
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
Если вы хотите поддерживать компилятор Windows 32bit C++Builder, вам придется переместить логику в файлы .h, которые используют для нее #pragma
, а затем вы можете #include
те файлы, где это необходимо (по крайней мере пока компилятор не будет обновлен для поддержки clang/C++11, над которым сейчас работает Embarcadero):
пакет1_begin.h:
#if defined(__BORLANDC__)
#define PACKED_BEGIN
#define PACKED
#define PACKED_END
#pragma pack(push, 1)
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
пакет_конец.ч:
#if defined(__BORLANDC__)
#pragma pack(pop)
#endif
Тогда вы можете сделать это:
#include "pack1_begin.h"
PACKED_BEGIN
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
PACKED_END
#include "pack_end.h"
Если вы выберете этот подход, вы можете просто вообще отказаться от PACKED_BEGIN
/PACKED_END
:
пакет1_begin.h:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define PACKED
#pragma pack(push, 1)
#elif defined(__GNUC__)
#define PACKED __attribute__((__packed__))
#else
#error PACKED macro is not defined for this compiler
#endif
пакет_конец.ч:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#pragma pack(pop)
#endif
#include "pack1_begin.h"
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
#include "pack_end.h"
person
Remy Lebeau
schedule
14.04.2015
#include "packed_begin.h"
и#include "packed_end.h"
(без охраны) - person Jarod42   schedule 14.04.2015