转义#define宏中的#符号?

Rob*_*Rob 37 c c++ macros c-preprocessor preprocessor-directive

在没有进入血腥细节的情况下,我想使用一个#define扩展为a 的宏,#include但是'#'符号会混淆预处理器(因为它认为我想引用一个参数.)

例如,我想做这样的事情:

#define MACRO(name) #include "name##foo"
Run Code Online (Sandbox Code Playgroud)

并使用它:

MACRO(Test)
Run Code Online (Sandbox Code Playgroud)

这将扩展到:

#include "Testfoo"
Run Code Online (Sandbox Code Playgroud)

简单的#符号导致预处理器进入barf.MinGW给我以下错误:

'#' is not followed by a macro parameter

我想我需要逃避#符号,但如果这是可能的话,我不会.

是的,宏确实很邪恶......

ybu*_*ill 32

可以插入一个哈希标记插入到预处理令牌流.你可以这样做:

#define MACRO(hash, name) hash include name
MACRO(#,"hello")
Run Code Online (Sandbox Code Playgroud)

- 扩展到:

# include "hello"
Run Code Online (Sandbox Code Playgroud)

但是,该标准明确排除了对此类行的任何进一步分析,以确定是否存在预处理指令[cpp.rescan]:

由此产生的完全宏替换的预处理标记序列不会作为预处理指令处理,即使它类似于预处理指令.


EFr*_*aim 29

据我所知,你不能在define中使用另一个预处理器指令.

  • 如果你提到你以哪种方式取得了你想要的东西,那就太好了?:-) (45认同)

MSa*_*ers 28

问题实际上并没有在预处理器的输出中获得#符号.

显然,您希望预处理器重新分析您的文件,以处理新创建的#include指令作为宏扩展的一部分.它不起作用.如果一行以#开头,则它是预处理器的指令并进行解释.如果一行不以#开头,则它只受预处理器转换的影响,包括宏替换.这是一次一次的测试.

MACRO(Test)
Run Code Online (Sandbox Code Playgroud)

不是以#开头.因此,它不被解释为预处理器指令; 相反,它受宏观替代规则的制约.

  • 我认为这里有最清晰的答案 - 实际上,他要求对预处理器进行第二次解析. (5认同)

Mar*_*ork 11

这是因为#在宏中使用时具有特殊含义.

#  means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.
Run Code Online (Sandbox Code Playgroud)

在您的情况下,#后面没有正确的令牌.所以在你的情况下,我们需要经历一个间接层次:

#define     QUOTE(name)     #name
#define     TEST(name)      QUOTE(name ## foo)

#include TEST(scot)
Run Code Online (Sandbox Code Playgroud)

  • 这适用于以下问题:要包含的名称不需要附加`.h`。在代码中包含#include USR_HEADER(name),并且希望它成为C的#include“ name.h”或#include“ cname”的情况下,使其难以工作。对于C ++。那是因为当其中一个标记是`.h'时,标记粘贴不起作用,并且在预处理程序完成后发生了字符串串联(因此生成`#include“ name”“ .h”`会使您得到无效的预处理程序指令) 。我还不确定如何解决这个问题,或者不确定<STdio.h>或<cstdio>的STD_HEADER(stdio)。 (2认同)

Joh*_*ode 6

你不能这样做.预处理器指令在宏扩展之前被识别; 如果宏扩展为看起来像预处理器指令的东西,则该指令将无法识别.您可以做的最好是为文件名创建一个宏:

#define MACRO(name) "name##foo"
...
#include MACRO(Test)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,现代预处理器不会扩展引号内的“名称”;无论传递给宏的值如何,这最终都会成为`#include "name##foo"`。 (2认同)