string化 – 它是如何工作的?
我知道:
#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" 。
为什么? 这个过程涉及哪些步骤?
macros观扩展的相关步骤是(根据C 2011 [n1570] 6.10.3.1和C ++ 1998 16.3.1):
- 处理以
#或##令牌。 - 将macrosreplace应用于每个参数。
- 将每个参数replace为上述macrosreplace的相应结果。
- 重新扫描更多的macros。
因此,用xstr(foo) ,我们有:
- replace文本
str(s)不包含#或##,所以没有任何反应。 -
foo的参数被replace为4,所以就好像xstr(4)已被使用。 - 在replace文本
str(s),参数s被replace为4,产生str(4)。 -
str(4)被重新扫描。 (由此产生的步骤产生”4”。
请注意, str(foo)的问题在于,第2步将用4replacefoo ,在第1步之后,将参数更改为string。 在第一步, foo还是foo ; 它并没有被4取代,所以结果是”foo” 。
这就是为什么使用助手macros的原因。 它允许我们执行第2步,然后使用另一个macros执行第1步。
第一种情况
- 评估
str(foo):用#fooreplacestr(foo),即"foo"
第二种情况
- 评估
xstr(foo):用str(<foo-value>)replacexstr(foo)str(<foo-value>),即str(4) - 评估
str(4):用#4replacestr(4),即"4"
通常,
预处理器评估扩展macrosvariables的macros函数, 直到没有任何评估 :
如果你定义
#define xstr(s) str(s) + 1 #define str(s) s + 1
在下面的代码中
#define foo 4 int main() { std::cout << str(foo) << '\n' << xstr(foo) << '\n' ; }
它会评估像
第一个string
- 用
<foo-value> + 1replacestr(foo),即4 + 1 - 没有什么可以替代的。 精加工。
结果是4 + 1
第二个string
- 用
str(<foo-value>) + 1replacexstr(foo),即str(4) + 1 - 用
<4-value> + 1代替str(4),即4 + 1 - 没有什么可以替代的。
结果是4 + 1 + 1