以下是与您的问题相关的一些概念:
参数预扫描:
宏参数在被替换为宏体之前完全被宏扩展,除非它们被字符串化或
与其他标记一起粘贴。替换后,将再次扫描整个宏体,包括被替换的参数,以查找要扩展的宏。结果是参数被扫描两次以扩展其中的宏调用。
串化
当宏参数与前导 '#' 一起使用时,预处理器将其替换为实际参数的文字文本,并转换为字符串常量。
#ABC => "ABC"
<---- 注意封闭的双引号,它是由字符串化过程添加的。
令牌粘贴/令牌连接:
在扩展宏时将两个标记合并为一个通常很有用。这称为令牌粘贴或令牌连接。'##' 预处理运算符执行令牌粘贴。扩展宏时,每个“##”运算符两侧的两个标记组合成一个标记,然后替换宏扩展中的“##”和两个原始标记。
所以你的场景的详细过程是这样的:
h(f(1,2))
-> h(12) // f(1,2) pre-expanded since there's no # or ## in macro h
-> g(12) // h expanded to g
"12" // g expanded as Stringification
g(f(1,2))
-> "f(1,2)" //f(1,2) is literally strigified because of the `#` in macro g. f(1,2) is NOT expanded at all.