C++ 字符串化 - 它是如何工作的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16989730/
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
Stringification - how does it work?
提问by Marco A.
I know that:
我知道:
#define foo 4
#define str(s) #s
with str(foo)
writes out: "foo"
, because stringify is executed first of text expansion, but this:
withstr(foo)
写出: "foo"
,因为 stringify 首先执行文本扩展,但是:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
with xstr(foo)
writes out: "4"
.
与xstr(foo)
写出:"4"
。
Why? What are the steps involved in the process?
为什么?该过程涉及哪些步骤?
回答by Eric Postpischil
The relevant steps of macro expansion are (per C 2011 [n1570] 6.10.3.1 and C++ 1998 16.3.1):
宏扩展的相关步骤是(根据 C 2011 [n1570] 6.10.3.1 和 C++ 1998 16.3.1):
- Process tokens that are preceded by
#
or##
. - Apply macro replacement to each argument.
- Replace each parameter with the corresponding result of the above macro replacement.
- Rescan for more macros.
- 处理以
#
或开头的标记##
。 - 对每个参数应用宏替换。
- 用上述宏替换的相应结果替换每个参数。
- 重新扫描更多宏。
Thus, with xstr(foo)
, we have:
因此,对于xstr(foo)
,我们有:
- The replacement text,
str(s)
, contains no#
or##
, so nothing happens. - The argument
foo
is replaced with4
, so it is as ifxstr(4)
had been used. - In the replacement text
str(s)
, the parameters
is replaced with4
, producingstr(4)
. str(4)
is rescanned. (The resulting steps produce”4”
.)
- 替换文本
str(s)
不包含#
或##
,因此什么也不会发生。 - 参数
foo
被替换为4
,因此就好像xstr(4)
被使用过一样。 - 在替换文本中
str(s)
,参数s
被替换为4
,生产str(4)
。 str(4)
被重新扫描。(由此产生的步骤产生”4”
.)
Note that the problem with str(foo)
is that step 2, which would replace foo
with 4
, comes after step 1, which changes the argument to a string. In step 1, foo
is still foo
; it has not been replaced with 4
, so the result is ”foo”
.
请注意,问题str(foo)
在于第 2 步(将替换foo
为4
)在第 1 步之后,它将参数更改为字符串。在步骤 1 中,foo
仍然是foo
; 它没有被替换为4
,所以结果是”foo”
。
This is why a helper macro is used. It allows us to get a step 2 performed, then use another macro to perform step 1.
这就是使用辅助宏的原因。它允许我们执行第 2 步,然后使用另一个宏执行第 1 步。
回答by Lol4t0
First case
第一种情况
- Evaluate
str(foo)
: Substitutestr(foo)
with#foo
, ie"foo"
- 评估
str(foo)
:替换str(foo)
为#foo
,即"foo"
Second case
第二种情况
- Evaluate
xstr(foo)
: Substitutexstr(foo)
withstr(<foo-value>)
, iestr(4)
- Evaluate
str(4)
: Substitutestr(4)
with#4
, ie"4"
- 评估
xstr(foo)
:替换xstr(foo)
为str(<foo-value>)
,即str(4)
- 评估
str(4)
:替换str(4)
为#4
,即"4"
Generally,
一般来说,
preprocessor evaluates macro-functions expanding macro-variables, until it is nothing to evaluate:
预处理器评估宏函数扩展宏变量,直到它没有评估:
If you define
如果你定义
#define xstr(s) str(s) + 1
#define str(s) s + 1
in the following code
在下面的代码中
#define foo 4
int main()
{
std::cout << str(foo) << '\n'
<< xstr(foo) << '\n' ;
}
it would evaluate like
它会评估像
First string
第一个字符串
- Substitute
str(foo)
with<foo-value> + 1
, ie4 + 1
- Nothing more to substitute. Finishing.
- 替换
str(foo)
为<foo-value> + 1
,即4 + 1
- 没有什么可以替代的了。精加工。
And result is 4 + 1
结果是 4 + 1
Second string
第二个字符串
- Substitute
xstr(foo)
withstr(<foo-value>) + 1
, iestr(4) + 1
- Substitute
str(4)
with<4-value> + 1
, ie4 + 1
- Nothing more to substitute.
- 替换
xstr(foo)
为str(<foo-value>) + 1
,即str(4) + 1
- 替换
str(4)
为<4-value> + 1
,即4 + 1
- 没有什么可以替代的了。
And result is 4 + 1 + 1
结果是 4 + 1 + 1