【问题标题】:Stringification - how does it work?字符串化——它是如何工作的?
【发布时间】:2013-06-04 02:13:51
【问题描述】:

我知道:

#define foo 4  
#define str(s) #s

str(foo) 写出:"foo",因为 stringify 是首先执行文本扩展,但是这样:

 #define xstr(s) str(s)
 #define str(s) #s
 #define foo 4

xstr(foo) 写出:"4"

为什么?流程中涉及哪些步骤?

【问题讨论】:

标签: c++ c c-preprocessor stringification


【解决方案1】:

宏扩展的相关步骤是(根据C 2011 [n1570] 6.10.3.1和C++ 1998 16.3.1):

  1. 处理前面带有### 的令牌。
  2. 对每个参数应用宏替换。
  3. 将每个参数替换为上述宏替换的对应结果。
  4. 重新扫描更多宏。

因此,使用xstr(foo),我们有:

  1. 替换文本str(s) 不包含###,因此没有任何反应。
  2. 参数foo 被替换为4,所以就好像使用了xstr(4)
  3. 在替换文本str(s)中,参数s被替换为4,产生str(4)
  4. str(4) 被重新扫描。 (生成的步骤产生”4”。)

请注意,str(foo) 的问题在于第 2 步(将用4 替换 foo)出现在第 1 步之后,它将参数更改为字符串。在步骤1中,foo仍然是foo;没有被4替换,所以结果是”foo”

这就是使用辅助宏的原因。它允许我们执行第 2 步,然后使用另一个宏执行第 1 步。

【讨论】:

  • 终于!在阅读了这个答案后,我终于明白了为什么会这样。我什至凭直觉正确使用它,但无法得出规则。 stringify 宏出现在许多地方(例如,将 __LINE__ 附加到标识符 - 以强制将其扩展而不是保留为 __LINE__,在这种情况下,您将使用 ## 而不是 #),或者 - 最近需要将参数传递给 GCC 的 _Pragma() 宏(内在?),它接受带引号的字符串,因此您可能需要:#define my_pragma(arg) _Pragma(stringify("blah " #arg " blah2"))
  • #define PE(BZL,YY) printf("ERROR - "#BZL": 结果: 0x%08x!", YY);做:int变量1=1; PE(测试1,变量1); --> 结果打印:错误 - 测试1:结果:0x1!
【解决方案2】:

第一种情况

  1. 评估str(foo):将str(foo)替换为#foo,即"foo"

第二种情况

  1. 评估xstr(foo):将xstr(foo) 替换为str(<foo-value>),即str(4)
  2. 评估str(4):将@​​987654330@ 替换为#4,即"4"

一般来说,

预处理器评估扩展宏变量的宏函数,直到它没有要评估的东西

如果你定义

#define xstr(s) str(s) + 1
#define str(s) s + 1

在下面的代码中

#define foo 4

int main()
{
    std::cout << str(foo) << '\n' 
              << xstr(foo) << '\n' ;

} 

它会像这样评估

第一个字符串

  1. str(foo) 替换为&lt;foo-value&gt; + 1,即4 + 1
  2. 没有什么可以替代的了。完成。

结果是 4 + 1

第二个字符串

  1. xstr(foo) 替换为str(&lt;foo-value&gt;) + 1,即str(4) + 1
  2. str(4) 替换为&lt;4-value&gt; + 1,即4 + 1
  3. 没有什么可以替代的。

结果是 4 + 1 + 1

【讨论】:

  • 我还是不明白.. 第一种情况:1)Stringify foo 2)展开,我现在有 foo。第二种情况:1)Stringify,没有什么可以stringify.. 2)展开,我现在有str(s)3)stringify,现在我有str(s)foo 4)展开,现在我有foo。为什么不一样??
  • @DavidKernin,嗯,你明白,'stringify'操作是#?这只是一步。
  • @DavidKernin,这并不像你想象的那么聪明。这很愚蠢。它只是扩展了一切。
  • 我明白了,它就像一堆函数......它只是不断替换,直到遇到 # 然后停止替换。如果没有其他#,则从这些“函数”替换继续返回。
猜你喜欢
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
相关资源
最近更新 更多