C / C ++宏字符串连接

问题描述 投票:101回答:3
#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

是否有可能连接STR3 ==“s1”?您可以通过将args传递给另一个宏函数来完成此操作。但是有直接的方法吗?

c++ c c-preprocessor
3个回答
134
投票

如果它们都是字符串,你可以这样做:

#define STR3 STR1 STR2

预处理器自动连接相邻的字符串。

编辑:

如下所述,它不是预处理器,而是执行串联的编译器。


93
投票

你不需要那种字符串文字的解决方案,因为它们在语言级别连接,并且它无论如何都不会起作用,因为“s”“1”不是有效的预处理器标记。但是,对于一般的令牌粘贴,请尝试以下方法:

/*
 * Concatenate preprocessor tokens A and B without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define PPCAT_NX(A, B) A ## B

/*
 * Concatenate preprocessor tokens A and B after macro-expanding them.
 */
#define PPCAT(A, B) PPCAT_NX(A, B)

然后,例如,PPCAT(s, 1)产生标识符s1

继续主题是这些宏:

/*
 * Turn A into a string literal without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define STRINGIZE_NX(A) #A

/*
 * Turn A into a string literal after macro-expanding it.
 */
#define STRINGIZE(A) STRINGIZE_NX(A)

然后,

#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"

23
投票

提示:上面的STRINGIZE宏很酷,但如果你犯了一个错误并且它的参数不是一个宏 - 你的名字中有一个拼写错误,或者忘了#include头文件 - 那么编译器会愉快地把声称的宏名称进入字符串没有错误。

如果你打算STRINGIZE的参数总是一个具有正常C值的宏,那么

#define STRINGIZE(A) ((A),STRINGIZE_NX(A))

将它扩展一次并检查它的有效性,丢弃它,然后再将它再次扩展为一个字符串。

我花了一段时间才弄清楚为什么STRINGIZE(ENOENT)最终成为"ENOENT"而不是"2" ...我没有包括errno.h

© www.soinside.com 2019 - 2024. All rights reserved.