在学习“预处理器运算符”时,我在一本书中找到了一个定义:
#define CONCAT(x,y) x##y
调用CONCAT(a,b)将提供所需的输出ab但是CONCAT(a,CONCAT(b,c))不会给出abc而是给出奇数输出。
Book解释说,替换列表中前面或后面##的宏参数在替换时不会展开因此CONCAT(a,CONCAT(b,c))扩展为aCONACT(b,c),无法进一步扩展,因为没有名为aCONCAT的宏。
好的,我明白了,但书中进一步提到,这个问题可以通过定义一个简单地调用第一个宏的第二个宏来解决例子
#define CONCAT2(x,y) CONCAT(x,y)
现在写入CONCAT2(a,CONCAT2(b,c))就可以得到所需的列表abc
但是怎么做呢我认为CONCAT2(a,CONCAT2 (b,c))将被CONCAT(a,CONCAT2(b,c))取代,后者将进一步扩展到aCONCAT2(b,c)现在没有一个名为aCONCAT2的宏,就像在第一种情况下一样,那么期望的输出是什么?
这证明CONCAT2(a,CONCAT2 (b,c))工作正常。
c - 预处理运算符“##”-LMLPHP
c - 预处理运算符“##”-LMLPHP
确保编译器不会显示任何错误除了使用getch()函数的警告。

最佳答案

如果你有

#define CONCAT(x,y)   x##y
#define CONCAT2(x,y)  CONCAT(x,y)

然后当预处理器看到
CONCAT(a,CONCAT(b,c))

它知道CONCAT(x,y)的替换列表是x###y,所以它将用CONCAT(b,c)替换x和y唯一的问题是,它会在替换之前扩展a和/或CONCAT(b,c)吗a不是宏,因此不可能展开,在替换列表x####y中,y前面是####,因此不会对参数CONCAT(b,c)进行展开因此,替换是在不扩展的情况下完成的,替换列表变成一个CONCAT(b,c),然后在它检查更多宏之前,它处理这个CONCAT(b,c)。
如果预处理器看到
CONCAT2(a,CONCAT2(b,c))

它知道CONCAT2(x,y)的替换列表是CONCAT2(x,y),所以它将用CONCAT2(b,c)替换x和y唯一的问题是,它会在替换之前展开a和/或CONCAT2(b,c)吗a不是宏,因此无法展开,并且在替换列表CONCAT(x,y)中,y前面没有#或###,后面没有##,因此CONCAT 2(b,c)在替换之前完全展开所以CONCAT2(b,c)被扩展到CONCAT2(b,c),CONCAT2(b,c)被扩展到b####c,不可能进一步扩展,所以y被b####c替换。替换列表x####y变成a########c,然后是a bc,或者它变成a#####c,然后是abc。
如果预处理器看到
CONCAT2(a,CONCAT(b,c))

它知道CONCAT2(x,y)的替换列表是CONCAT(x,y),所以它将用CONCAT(b,c)替换x和y唯一的问题是,它会在替换之前扩展a和/或CONCAT(b,c)吗a不是宏,因此无法展开,并且在替换列表CONCAT(x,y)中,y前面没有#或###,后面没有###,因此CONCAT(b,c)在替换之前完全展开所以CONCAT(b,c)被扩展到b###c,不可能再进一步扩展,所以y被b####c替换,替换列表x####y变成a#########c,或者它变成a####c,然后变成a bc。
如果预处理器看到
CONCAT(a,CONCAT2(b,c))

它知道CONCAT(x,y)的替换列表是x###y,所以它将用CONCAT 2(b,c)替换x和y唯一的问题是,它会在替换之前展开a和/或CONCAT2(b,c)吗a不是宏,因此不可能展开,在替换列表x####y中,y前面是####,因此不会对参数CONCAT2(b,c)进行展开因此,替换是在不进行扩展的情况下完成的,替换列表变为一个CONCAT2(b,c),然后在检查更多宏之前,它处理这个CONCAT2(b,c)。
你可能在想
#define CONCAT2(x,y)  CONCAT(x,y)

意思是
CONCAT2(x,y)应与CONCAT(x,y)相同
但请记住:
CONCAT(x,y)的替换列表是x###y,并且由于x后面跟着###,y前面跟着###,因此当预处理器看到CONCAT宏的实例时,它不会在替换之前展开与x或y对应的参数然而,CONCAT2(x,y)的替换列表是CONCAT(x,y),替换中的x和y前面都没有##或###或后面都没有###,因此当预处理器看到CONCAT2宏的实例时,它将在替换之前完全展开argmuments中的任何宏。
参数的宏扩展(如果允许)在替换之前进行所以在CONCAT2(a,CONCAT(b,c))中,CONCAT(b,c)参数在替换之前展开所以我们得到CONCAT 2(a,b#c)而不是CONCAT(a,CONCAT(b,c))。

09-20 10:27