在Borland C ++上使用#pragma pack和#define

时间:2015-04-14 14:28:01

标签: c++ c++builder pragma borland-c++

我正在尝试使用Borland C ++ Builder(XE6)打包一些结构(将来:bcc)。

我使用的库使用以下构造来创建结构:

#ifdef _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
#endif


PACKED_BEGIN
struct PACKED {
    short someSampleShort;
    char sampleByte;
    int sampleInteger;
} structType_t;
PACKED_END

bcc编译器不喜欢MSC __pragma,并且不喜欢宏内部的预处理器指令,尽管它在their website中有描述:

#define GETSTD #include <stdio.h>

我的问题是:是否有可能将此构造与Borland编译器一起用于打包结构而不使用

#pragma pack(1) 

打包每个结构?

这有什么变通方法吗?

2 个答案:

答案 0 :(得分:3)

正如您所说,C ++ Builder不支持宏内的预处理程序语句。这在Embarcadero的网站上有记录:

#define (C++)

  

在每次单独的宏扩展之后,进一步扫描新扩展的文本。这允许嵌套宏的可能性:扩展文本可以包含可替换的宏标识符。 但是,如果宏扩展为看起来像预处理指令的内容,预处理器将无法识别该指令。

原因是因为宏内的#字符是为预处理器的字符串化运算符保留的。

某些编译器(包括MSVC)使用__pragma()编译器扩展或C99 / C ++ x0 _Pragma()扩展来绕过该限制。 C ++ Builder的 Windows 32位编译器不支持其中任何一种。但是,其 Windows 64位移动编译器(均基于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

如果您想支持C ++ Builder Windows 32位编译器,则必须将逻辑移动到使用#pragma的.h文件中,然后您可以{ {1}}需要的那些文件(至少在更新编译器以支持clang / C ++ 11 - Embarcadero目前正在进行的工作之前):

pack1_begin.h:

#include

pack_end.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

pack1_begin.h:

PACKED_END

pack_end.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

答案 1 :(得分:0)

该标准为编写pragma提供了一个额外的选择:_Pragma运算符:

#define PACKED_BEGIN _Pragma("pack(push, 1)")
#define PACKED 
#define PACKED_END _Pragma("pack(pop)")

如果Borland编译器支持它,它应该可以工作。