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

use*_*582 5 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
Run Code Online (Sandbox Code Playgroud)

bcc编译器不喜欢MSC __pragma,并且不喜欢宏内部的预处理器指令,尽管它们在他们的网站上有描述:

#define GETSTD #include <stdio.h>
Run Code Online (Sandbox Code Playgroud)

我的问题是:是否有可能在Borland编译器中使用此构造来打包结构而不使用:

#pragma pack(1) 
Run Code Online (Sandbox Code Playgroud)

打包每个结构?

这有什么变通方法吗?

Rem*_*eau 3

正如您所说,C++Builder 不支持宏内部的预处理器语句。Embarcadero 网站上对此进行了记录:

#定义 (C++)

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

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

__pragma()一些编译器(包括 MSVC)通过编译器扩展或 C99/C++x0扩展来绕过该限制_Pragma()。C++Builder 的Windows 32 位编译器不支持其中任何一个。但是,其Windows 64 位移动编译器(均基于 clang 并支持 C++11)确实支持这两者。因此,您可以在宏中添加对这些编译器的支持,如下所示:

#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
Run Code Online (Sandbox Code Playgroud)

如果您想支持 C++Builder Windows 32 位编译器,则必须将逻辑移至使用#pragma它的 .h 文件中,然后您可以#include在需要的地方使用这些文件(至少直到编译器更新为支持 clang/ C++11 - Embarcadero 目前正在开发):

pack1_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
Run Code Online (Sandbox Code Playgroud)

pack_end.h:

#if defined(__BORLANDC__)
    #pragma pack(pop)
#endif
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

#include "pack1_begin.h"
PACKED_BEGIN
struct PACKED {
    short someSampleShort;
    char sampleByte;
    int sampleInteger;
} structType_t;
PACKED_END
#include "pack_end.h"
Run Code Online (Sandbox Code Playgroud)

如果您采用这种方法,您可以完全删除PACKED_BEGIN/ PACKED_END

pack1_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
Run Code Online (Sandbox Code Playgroud)

pack_end.h:

#if defined(__BORLANDC__) || defined(_MSC_VER)
    #pragma pack(pop)
#endif
Run Code Online (Sandbox Code Playgroud)

#include "pack1_begin.h"
struct PACKED {
    short someSampleShort;
    char sampleByte;
    int sampleInteger;
} structType_t;
#include "pack_end.h"
Run Code Online (Sandbox Code Playgroud)