宏定义中的Pragma

118

有没有办法在宏中嵌入包含其他语句的pragma语句?

我想要实现如下功能:

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

如果有boost的解决方案(除了wave),我可以接受。


5
可以说这不属于任何一种——#pragma指令既不是由C标准定义的,也不是由C++标准定义的。 - anon
1
预处理器是可以运行的,即使他想要运行的特定允许子命令不是。 - Puppy
@DeadMG:C和C++之间有许多共同点。虽然预处理在大部分情况下是相同的,但是根据使用的语言标准(C89、C99、C++和C++0x FCD),预处理的规范存在重大差异。 - James McNellis
2
@James McNellis:仅仅因为在技术上,大多数C程序可以移植到C++,并不意味着这是真正的共同功能,因为没有C++程序员会使用其中绝大部分。这两种语言实际上没有太多共同之处。 - Puppy
4个回答

134

如果您正在使用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
 ;

35
FYI:MSVC有__pragma()预处理器运算符,不幸的是它与C99的_Pragma()运算符略有不同(C99的需要一个字符串字面量,而MSVC的需要不在字符串中的标记):http://msdn.microsoft.com/en-us/library/d9x1s805.aspx - Michael Burr
18
@MichaelBurr MSVC总是与众不同,不是吗? - Thomas

6

您可以使用 _Pragma("argument") 处理一些与编译器相关的问题,例如:

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

2

不,没有通用的方法可以做到这一点。但是,就算是使用#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定义为带参数的宏,但我不想阅读有关如何为此示例创建弱定义的文档。我将其留给读者作为练习。


-3
有没有办法在宏中嵌入其他语句的编译指示语句?
不行,你不能把预处理器语句放到另一个预处理器语句里面。但是你可以将它放到一个内联函数中。然而,这会破坏 C 标签。

1
把它放到内联函数中有什么好处呢?预处理指令在任何能识别函数的东西之前被处理。 - anon
2
C99有inline,而大多数主要的C89实现都有一些变化。 - Chris Lutz
@Chris 假设你的评论是针对我的 - 你的观点是什么? - anon
@Neil - 不好意思,我是在回应@sbi的最后一句话。 - Chris Lutz
@Neil:我不知道那个编译指示应该做什么。 - sbi
1
@Chris:啊,所以“inline”是C从C++借鉴的又一个东西!:) - sbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接