C/C++宏字符串连接

发布于 2024-10-21 01:59:34 字数 209 浏览 1 评论 0原文

#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

是否可以将 STR1STR2 连接到 "s1"? 您可以通过将参数传递给另一个宏函数来完成此操作。但有没有直接的方法呢?

#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

Is it possible to concatenate STR1 and STR2, to "s1"?
You can do this by passing args to another Macro function. But is there a direct way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鹿! 2024-10-28 01:59:34

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

#define STR3 STR1 STR2

这然后扩展为:

#define STR3 "s" "1"

在 C 语言中,用空格分隔两个字符串,如 "s" "1" 完全等同于拥有单个字符串“s1”

If they're both strings you can just do:

#define STR3 STR1 STR2

This then expands to:

#define STR3 "s" "1"

and in the C language, separating two strings with space as in "s" "1" is exactly equivalent to having a single string "s1".

顾北清歌寒 2024-10-28 01:59:34

您不需要针对字符串文字的此类解决方案,因为它们是在语言级别连接的,而且无论如何它都不起作用,因为“s”“1”不是有效的预处理器标记。

[编辑:为了回应下面错误的“仅供记录”评论,不幸的是收到了一些赞成票,我将重申上面的声明,并观察到程序片段

#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")

在 gcc 的预处理阶段产生了此错误消息:错误:粘贴“”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_NX(s, 1)PPCAT_NX(s, 1) 和 PPCAT(s, 1) 生成标识符 s1,除非 s 被定义为宏,在这种情况下 PPCAT (s, 1) 产生 1

继续主题是这些宏:

/*
 * 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"

相比之下,

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)"

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.

[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

]

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.

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)"
合久必婚 2024-10-28 01:59:34

提示:上面的 STRINGIZE 宏很酷,但是如果您犯了一个错误,并且它的参数不是宏 - 您的名称有拼写错误,或者忘记了#include 头文件 - 那么编译器会很高兴地将所谓的宏名称放入字符串中,不会出现错误。

如果您希望 STRINGIZE 的参数始终是具有普通 C 值的宏,则将

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

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

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

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.

If you intend that the argument to STRINGIZE is always a macro with a normal C value, then

#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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文