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

标签 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) 

打包每个结构?

是否有任何解决方法?

最佳答案

如您所述,C++Builder 不支持宏内部的预处理器语句。这记录在 Embarcadero 的网站上:

#define (C++)

After each individual macro expansion, a further scan is made of the newly expanded text. This allows for the possibility of nested macros: The expanded text can contain macro identifiers that are subject to replacement. However, if the macro expands into what looks like a preprocessing directive, the directive will not be recognized by the preprocessor.

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

某些编译器(包括 MSVC)通过 __pragma() 编译器扩展或 C99/C++x0 _Pragma() 扩展来绕过该限制。 C++Builder 的 Windows 32bit 编译器不支持其中任何一个。但是,它的 Windows 64bitmobile 编译器(均基于 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 32bit 编译器,你必须将逻辑移动到使用 #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

pack_end.h:

#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:

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

pack_end.h:

#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"

关于c++ - 在 Borland C++ 上使用#pragma pack 和#define,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29630011/

相关文章:

c++ - "dreaded diamond"具有多态性

c - 如何检查unicode字符是否在C中的给定范围内?

delphi - 带 SSL 的 TCP/IP - Delphi 和 Indy10

iphone - Apple LLVM 编译器 - 使用编译指示来禁止文件一部分的所有警告?

c# - 如何处理The type 'Foo' in 'File1.cs'与导入的type 'Foo' in 'File2.dll'警告

c - # pragma 指令及其在 C 语言中的用途

c++ - 以编程方式读取网页

c++ - 崩溃后检查 gdb 回溯中的 C++ 对象

c# - PostgreSQL C++ Api 收到错误 LNK1107 : invalid or corrupt file: cannot read at 0x2E8

delphi - 如何在C++ Builder XE6中部署大量文件?