【问题标题】:Replacement and stringification of #define#define 的替换和字符串化
【发布时间】:2012-10-08 17:06:07
【问题描述】:

我正在尝试了解替换 same2、same1 和 concatenate in 的流程:

#include<stdio.h>
#define concatenate(a,b) a##b
#define same1(a)  #a
#define same2(a)  same1(a)
main()
{
        printf("%s\n",same2(concatenate(1,2)));
        printf("%s\n",same1(concatenate(1,2)));
}

我试图从很多地方理解这一点,但我无法理解。有人能解释清楚吗?

【问题讨论】:

    标签: c c-preprocessor stringification


    【解决方案1】:

    #define concatenate(a,b) a##b
    #define same1(a)  #a
    #define same2(a)  same1(a)
    

    当你有same2(concatenate(1,2)) 时,same2 的参数在传递给same1 之前会被扩展,所以concatenate(1,2) 被它的结果替换,12 然后被same1 字符串化为产生"12"

    使用same1,宏参数不会发生扩展,因为它前面是字符串化标记#

    在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 ### 预处理标记或后面跟着 ## 预处理标记(见下文),在其中包含的所有宏都已展开后,将替换为相应的参数。在被替换之前,每个参数的预处理标记都被完全宏替换,就好像它们形成了预处理文件的其余部分一样;没有其他可用的预处理令牌。

    (n1570 中的第 6.10.3.1 (1) 节)

    【讨论】:

    • Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.你能解释一下吗?
    • “好像它们形成了其余部分......”意味着后面定义的宏不在范围内,只有之前定义的宏,所以如果其中一个标记与这样的宏匹配,则不是更换。这就是你想要解释的吗?
    • Daniel,我感谢您的努力,但我仍然怀疑为什么 same2(concatenate(1,2)) 将 concatenate(1,2) 替换为 1##2,然后将 same2 替换为 same1。但这不会发生,所以当我用 same1(concatenate(1,2)); 尝试同样的事情时表示为什么 concatenate(1,2) 不先被 1##2 替换?
    • same2(a) 被定义为same1 ( a )(添加空格来分隔标记)。现在参数 (a) 前面没有###,后面也没有##,所以在调用same2 时,传递的参数是宏扩展的。当参数为concatenate(1,2) 时,调用宏concatenate,参数12 给出1 ## 2,然后应用## 运算符(在重新扫描令牌序列以获取更多宏之前替换)产生令牌12。它不再包含宏名称,所以它被传递给same1,所以我们在same1 ( 12 )
    • 现在,替换same2 的参数的结果被重新扫描以查找宏调用(但same2,如果它作为令牌出现,则不会再次被替换)。根据same1 的定义,结果为# 12。然后应用# 运算符,生成"12"。在 same1 的替换列表中,参数 (a) 前面有一个 # 标记,因此在重新扫描替换列表以进行宏扩展之前应用了字符串化运算符,因此字符串的创建发生在它之前检查参数是否包含宏调用。
    【解决方案2】:

    当 1 和 2 作为参数传递时,您的 concatinate(a,b) 变为 concatinate(1,2)。这又变成了1##2,它转换为12,因为## 是一个连接运算符。所以参数 1 和 2 连接起来变成 12

    Same1(a) 变成简单的#a,其中# 是字符串化操作符(参见http://c-faq.com/ansi/stringize.html)。所以Same1(12) 变成"12" 并打印到控制台时

    Same2(a)Same1(a)一样,就是#a,只是原样输出参数a;所以Same2(a) 的输出,其中参数 a 是 'Concatenate(1,2)' 只是一个字符串 "Concatenate(1,2)"

    【讨论】:

    • 你说的完全相反。输出为: 12 concatenate(1,2)
    • 是的,第一个printf的参数变成了#(a##b),其中a为1,b为2,所以变成了“12”;第二个 printf 的参数只是 #a 变成“concatinate(1,2)”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 2015-04-26
    • 2017-03-07
    • 1970-01-01
    • 2017-12-24
    相关资源
    最近更新 更多