定义宏中的编译指示
Posted
技术标签:
【中文标题】定义宏中的编译指示【英文标题】: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++ 程序员都不会这样做。这两种语言实际上并没有太多共同点。 【参考方案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_b
和 Weak_e
定义为开头和结尾的括号结构并不明显,因为一些编译器(如 GCC)将属性作为附录添加到类型签名中,而另一些编译器(如 MSC)添加它作为前缀(或者至少它做过一次,自从我使用 MSC 已经有好几年了)。即使您必须将整个类型签名传递给编译器构造,使用括号结构也可以定义始终有效的东西。
当然,如果您尝试将其移植到没有您想要的属性的编译器,那么您无能为力,只能将宏扩展为空,并希望您的代码仍然可以运行。在纯粹的警告或优化编译指示的情况下,这很可能。在其他情况下,没有那么多。
哦,我怀疑您实际上需要将 Weak_b 和 Weak_e 定义为带参数的宏,但我不愿意通读文档以了解如何仅为此示例创建弱定义。我把它留给读者作为练习。
【讨论】:
【参考方案4】:有没有办法在宏中嵌入 pragma 语句和其他语句?
不,您不能将预处理器语句放入预处理器语句中。但是,您可以将其放入 inline
函数中。不过,这会破坏C
标签。
【讨论】:
将它放入内联函数有什么好处?预处理器指令在任何可以识别函数的东西之前被处理。 C99 有inline
,大多数主要的 C89 实现都有一些变化。
@Chris 假设你的评论是针对我的 - 你的意思是 - 什么?
@Neil - 不,抱歉。我把它指向@sbi 的最后一句话。
@Chris:啊,所以inline
是 C 从 C++ 借来的另一个东西! :)
以上是关于定义宏中的编译指示的主要内容,如果未能解决你的问题,请参考以下文章