编译器用这个宏看到了什么?

joh*_*ers 9 stringification c-preprocessor

考虑一下:

  #define STRINGIFY(A) #A
Run Code Online (Sandbox Code Playgroud)

如果我后来写道:

 STRINGIFY(hello)
Run Code Online (Sandbox Code Playgroud)

编译器实际上看到了这个:

 #hello
Run Code Online (Sandbox Code Playgroud)

我认为前面的额外哈希#A让我感到困惑.

mil*_*bug 15

编译器看到的是:

"hello"
Run Code Online (Sandbox Code Playgroud)

哈希是仅预处理程序的标记.

单个哈希对参数进行字符串化.

#define STRINGIFY(x) #x
STRINGIFY(hello)
Run Code Online (Sandbox Code Playgroud)

被替换为

"hello"
Run Code Online (Sandbox Code Playgroud)

双哈希连接令牌:

#define CAT(a, b) a##b
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
STRINGIFY(CAT(hello,world))
Run Code Online (Sandbox Code Playgroud)

被这取代:

_STRINGIFY(helloworld)
Run Code Online (Sandbox Code Playgroud)

然后由此:

"helloworld"
Run Code Online (Sandbox Code Playgroud)

编辑:正如Pubby指出的那样,这个例子是错误的,宏替换不起作用,但现在我纠正了它.


eff*_*ffe 10

不,编译器会将参数放在引号之间,从而导致:

"hello"
Run Code Online (Sandbox Code Playgroud)

但是,要注意的是宏替换不会发生近###,所以如果你真的需要字符串化的参数(即使它是另一个宏),最好写两个宏,第一个展开争论,另一个加报价:

#define STRINGIFY(x) STRINGIFY_AUX(x)
#define STRINGIFY_AUX(x) #x
Run Code Online (Sandbox Code Playgroud)

或者更一般地说,如果您的编译器支持可变参数宏(在C99中引入):

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__
Run Code Online (Sandbox Code Playgroud)

如果你真的需要一个类似函数的宏来粘贴#参数的开头,我认为你需要它来生成一个字符串(否则你会为编译器创建一个无效的标记),所以你可以简单地生成两个字符串文字编译器将"粘贴":

#include <stdio.h>

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__

int main(void)
{
  puts(STRINGIFY(#) STRINGIFY(hello));
}
Run Code Online (Sandbox Code Playgroud)

main在预处理器输出中,正文将如下所示:

puts("#" "hello");
Run Code Online (Sandbox Code Playgroud)

我希望这不是预处理器的一个模糊角落导致未定义的行为,但它不应该是一个问题,因为我们没有生成另一个预处理器指令.


Vin*_*Pii 9

您可以使用-E(*)标志(使用gcc/g ++)自行测试:

TEST.CPP

#define STRINGIFY(A) #A

int main(int argc, const char *argv[])
{
    STRINGIFY(hello);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出 g++ test.cpp -E

# 1 "test.cpp"
# 1 "<command-line>"
# 1 "test.cpp"


int main(int argc, const char *argv[])
{
    "hello";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(*):If you use the -E option, nothing is done except preprocessing.- GCC选项控制预处理器