C/C++ 宏字符串连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5256313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C/C++ macro string concatenation
提问by tvr
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
Is it possible to concatenate have STR3 == "s1"? You can do this by passing args to another Macro function. But is there a direct way?
是否可以连接 STR3 == "s1"?您可以通过将 args 传递给另一个宏函数来做到这一点。但是有直接的方法吗?
回答by Sean
If they're both strings you can just do:
如果它们都是字符串,您可以这样做:
#define STR3 STR1 STR2
The preprocessor automatically concatenates adjacent strings.
预处理器会自动连接相邻的字符串。
EDIT:
编辑:
As noted below, it's not the preprocessor but the compiler that does the concatenation.
如下所述,进行连接的不是预处理器,而是编译器。
回答by Jim Balter
You don't need that sort of solution for string literals, since they are concatenated at the language level, and it wouldn't work anyway because "s""1" isn't a valid preprocessor token.
对于字符串文字,您不需要那种解决方案,因为它们是在语言级别连接的,而且无论如何它都不起作用,因为 "s""1" 不是有效的预处理器标记。
[Edit: In response to the incorrect "Just for the record" comment below that unfortunately received several upvotes, I will reiterate the statement above and observe that the program fragment
[编辑:为了回应下面不正确的“仅供记录”评论,不幸的是收到了几个赞成票,我将重申上述声明并观察程序片段
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
produces this error message from the preprocessing phase of gcc: error: pasting ""s"" and ""1"" does not give a valid preprocessing token
从 gcc 的预处理阶段产生此错误消息:错误:粘贴 ""s"" 和 ""1"" 没有给出有效的预处理标记
]
]
However, for general token pasting, try this:
但是,对于一般令牌粘贴,请尝试以下操作:
/*
* 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)
Then, e.g., both PPCAT_NX(s, 1)
and PPCAT(s, 1)
produce the identifier s1
, unless s
is defined as a macro, in which case PPCAT(s, 1)
produces <macro value of s>1
.
然后,例如,两者PPCAT_NX(s, 1)
并PPCAT(s, 1)
产生所述标识符s1
,除非s
被定义为一个宏,在这种情况下PPCAT(s, 1)
产生的<macro value of s>1
。
Continuing on the theme are these macros:
继续主题是这些宏:
/*
* 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)
Then,
然后,
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
By contrast,
相比之下,
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"
#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
回答by Jordan Brown
Hint: The STRINGIZE
macro above is cool, but if you make a mistake and its argument isn't a macro - you had a typo in the name, or forgot to #include
the header file - then the compiler will happily put the purported macro name into the string with no error.
提示:STRINGIZE
上面的宏很酷,但是如果你犯了一个错误并且它的参数不是宏——你的名字有错别字,或者忘记#include
了头文件——那么编译器会很高兴地把所谓的宏名称放入没有错误的字符串。
If you intend that the argument to STRINGIZE
is always a macro with a normal C value, then
如果您希望参数STRINGIZE
始终是一个具有普通 C 值的宏,那么
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
will expand it once and check it for validity, discard that, and then expand it again into a string.
将其展开一次并检查其有效性,丢弃它,然后再次将其展开为一个字符串。
It took me a while to figure out why STRINGIZE(ENOENT)
was ending up as "ENOENT"
instead of "2"
... I hadn't included errno.h
.
我花了一段时间才弄明白为什么STRINGIZE(ENOENT)
最后变成了"ENOENT"
而不是"2"
......我没有包括errno.h
.