11

考虑一下:

  #define STRINGIFY(A) #A

如果我后来写:

 STRINGIFY(hello)

编译器是否真的看到了这个:

 #hello

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

4

4 回答 4

17

编译器看到的是这样的:

"hello"

哈希是仅预处理器的令牌。

单个哈希将参数字符串化。

#define STRINGIFY(x) #x
STRINGIFY(hello)

被取代

"hello"

双哈希连接标记:

#define CAT(a, b) a##b
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
STRINGIFY(CAT(hello,world))

被这个取代:

_STRINGIFY(helloworld)

然后通过这个:

"helloworld"

编辑:正如 Pubby 指出的那样,这个例子是错误的,宏替换不是那样工作的,但现在我更正了。

于 2012-12-23T13:56:56.747 回答
11

不,编译器会将参数放在引号之间,结果如下:

"hello"

但是,请注意宏替换不会在#and附近发生##,因此如果您确实需要对参数进行字符串化(即使它是另一个宏),最好编写两个宏,第一个用于扩展参数,另一个用于添加引号:

#define STRINGIFY(x) STRINGIFY_AUX(x)
#define STRINGIFY_AUX(x) #x

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

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

#如果您确实需要一个在参数开头粘贴 a 的类似函数的宏,我认为您需要它来生成一个字符串(否则您会为编译器制作一个无效的标记),因此您可以简单地生成两个字符串文字编译器将“粘贴”:

#include <stdio.h>

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

int main(void)
{
  puts(STRINGIFY(#) STRINGIFY(hello));
}

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

puts("#" "hello");

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

于 2012-12-23T14:11:45.380 回答
10

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

测试.cpp

#define STRINGIFY(A) #A

int main(int argc, const char *argv[])
{
    STRINGIFY(hello);
    return 0;
}

的输出g++ test.cpp -E

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


int main(int argc, const char *argv[])
{
    "hello";
    return 0;
}

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

于 2012-12-23T14:00:13.553 回答
3

在这里找到了在预处理器中使用散列的简单解释:

http://www.cplusplus.com/doc/tutorial/preprocessor/

于 2012-12-23T14:07:34.937 回答