【问题标题】:Pragma in define macro定义宏中的编译指示
【发布时间】:2011-03-03 02:05:13
【问题描述】:

有没有办法在宏中嵌入 pragma 语句和其他语句?

我正在尝试实现以下目标:

#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type_(int handle);                  \
    void delete_ ## type(int handle);                                                \
    #pragma weak delete_ ## type_ = delete_ ## type

如果存在提升解决方案(除了 wave),我可以接受。

【问题讨论】:

  • 可以说两者都不是 - #pragmas 不是由 C 或 C++ 标准定义的。
  • 预处理器是,即使他想要运行的特定允许子命令不是。
  • @DeadMG:C 和 C++ 之间有很多共同点。虽然预处理大部分很常见,但根据所使用的语言标准(C89、C99、C++ 和 C++0x FCD),如何指定预处理存在重大差异。
  • @James McNellis:仅仅因为从技术上讲,大多数 C 程序都可以移植到 C++ 中,因此并没有真正实现通用功能,因为绝大多数 C++ 程序员都不会这样做。这两种语言实际上并没有太多共同点。

标签: c-preprocessor pragma stringification


【解决方案1】:

如果您使用的是 c99 或 c++0x,则有 pragma 运算符,用作

_Pragma("argument")

相当于

#pragma argument

除了它可以在宏中使用(参见 c99 标准的第 6.10.9 节,或 c++0x 最终委员会草案的第 16.9 节)

例如,

#define STRINGIFY(a) #a
#define DEFINE_DELETE_OBJECT(type)                      \
    void delete_ ## type ## _(int handle);                  \
    void delete_ ## type(int handle);                   \
    _Pragma( STRINGIFY( weak delete_ ## type ## _ = delete_ ## type) )
DEFINE_DELETE_OBJECT(foo);

当放入gcc -E 时会给出

void delete_foo_(int handle); void delete_foo(int handle);
#pragma weak delete_foo_ = delete_foo
 ;

【讨论】:

  • 仅供参考:MSVC 具有 __pragma() 预处理器运算符,不幸的是,它与 C99 的 _Pragma() 运算符略有不同(C99 采用字符串文字,MSVC 采用不在字符串中的标记) :msdn.microsoft.com/en-us/library/d9x1s805.aspx
  • @MichaelBurr MSVC 总是必须与众不同,不是吗?
【解决方案2】:

您可以使用 _Pragma("argument") 做的一件好事是使用它来处理一些编译器问题,例如

#ifdef _MSC_VER
#define DUMMY_PRAGMA _Pragma("argument")
#else
#define DUMMY_PRAGMA _Pragma("alt argument")
#endif

【讨论】:

    【解决方案3】:

    不,没有便携的方法可以做到这一点。再说一次,根本没有可移植的方式来使用#pragma。正因为如此,许多 C/C++ 编译器定义了自己的方法来执行类似 pragma 的事情,并且它们通常可以嵌入到宏中,但是每个编译器都需要不同的宏定义。如果你愿意走这条路,你通常会做这样的事情:

    #if defined(COMPILER_GCC)
    #define Weak_b
    #define Weak_e __attribute__((weak))
    #elif defined(COMPILER_FOO)
    #define Weak_b __Is_Weak
    #define Weak_e
    #endif
    
    #define DEFINE_DELETE_OBJECT(type)                      \
        Weak_b void delete_ ## type_(int handle) Weak_e;    \
        Weak_b void delete_ ## type(int handle)  Weak_e;    
    

    如果您想将 Weak_bWeak_e 定义为开头和结尾的括号结构并不明显,因为一些编译器(如 GCC)将属性作为附录添加到类型签名中,而另一些编译器(如 MSC)添加它作为前缀(或者至少它做过一次,自从我使用 MSC 已经有好几年了)。即使您必须将整个类型签名传递给编译器构造,使用括号结构也可以定义始终有效的东西。

    当然,如果您尝试将其移植到没有您想要的属性的编译器,那么您无能为力,只能将宏扩展为空,并希望您的代码仍然可以运行。在纯粹的警告或优化编译指示的情况下,这很可能。在其他情况下,没有那么多。

    哦,我怀疑您实际上需要将 Weak_b 和 Weak_e 定义为带参数的宏,但我不愿意通读文档以了解如何仅为此示例创建弱定义。我把它留给读者作为练习。

    【讨论】:

      【解决方案4】:

      有没有办法在宏中嵌入 pragma 语句和其他语句?

      不,您不能将预处理器语句放入预处理器语句中。但是,您可以将其放入 inline 函数中。不过,这会破坏C 标签。

      【讨论】:

      • 将它放入内联函数有什么好处?预处理器指令在任何可以识别函数的东西之前被处理。
      • C99 有 inline,大多数主要的 C89 实现都有一些变化。
      • @Chris 假设你的评论是针对我的 - 你的意思是 - 什么?
      • @Neil - 不,抱歉。我把它指向@sbi 的最后一句话。
      • @Chris:啊,所以inline 是 C 从 C++ 借来的另一个东西! :)
      猜你喜欢
      • 1970-01-01
      • 2012-11-29
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多