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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:48:26  来源:igfitidea点击:

Stringification - how does it work?

c++cc-preprocessorstringification

提问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):

  1. Process tokens that are preceded by #or ##.
  2. Apply macro replacement to each argument.
  3. Replace each parameter with the corresponding result of the above macro replacement.
  4. Rescan for more macros.
  1. 处理以#或开头的标记##
  2. 对每个参数应用宏替换。
  3. 用上述宏替换的相应结果替换每个参数。
  4. 重新扫描更多宏。

Thus, with xstr(foo), we have:

因此,对于xstr(foo),我们有:

  1. The replacement text, str(s), contains no #or ##, so nothing happens.
  2. The argument foois replaced with 4, so it is as if xstr(4)had been used.
  3. In the replacement text str(s), the parameter sis replaced with 4, producing str(4).
  4. str(4)is rescanned. (The resulting steps produce ”4”.)
  1. 替换文本str(s)不包含###,因此什么也不会发生。
  2. 参数foo被替换为4,因此就好像xstr(4)被使用过一样。
  3. 在替换文本中str(s),参数s被替换为4,生产str(4)
  4. str(4)被重新扫描。(由此产生的步骤产生”4”.)

Note that the problem with str(foo)is that step 2, which would replace foowith 4, comes after step 1, which changes the argument to a string. In step 1, foois still foo; it has not been replaced with 4, so the result is ”foo”.

请注意,问题str(foo)在于第 2 步(将替换foo4)在第 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

第一种情况

  1. Evaluate str(foo): Substitute str(foo)with #foo, ie "foo"
  1. 评估str(foo):替换str(foo)#foo,即"foo"

Second case

第二种情况

  1. Evaluate xstr(foo): Substitute xstr(foo)with str(<foo-value>), ie str(4)
  2. Evaluate str(4): Substitute str(4)with #4, ie "4"
  1. 评估xstr(foo):替换xstr(foo)str(<foo-value>),即str(4)
  2. 评估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

第一个字符串

  1. Substitute str(foo)with <foo-value> + 1, ie 4 + 1
  2. Nothing more to substitute. Finishing.
  1. 替换str(foo)<foo-value> + 1,即4 + 1
  2. 没有什么可以替代的了。精加工。

And result is 4 + 1

结果是 4 + 1

Second string

第二个字符串

  1. Substitute xstr(foo)with str(<foo-value>) + 1, ie str(4) + 1
  2. Substitute str(4)with <4-value> + 1, ie 4 + 1
  3. Nothing more to substitute.
  1. 替换xstr(foo)str(<foo-value>) + 1,即str(4) + 1
  2. 替换str(4)<4-value> + 1,即4 + 1
  3. 没有什么可以替代的了。

And result is 4 + 1 + 1

结果是 4 + 1 + 1