预处理运算符“##”
Preprocessing operator "##"
在学习 'Preprocessor Operators' 时,我在一本书中找到了一个定义:
#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))
工作正常的证明。
看到编译器不会显示任何错误。除了使用 getch( ) 函数的警告。
如果你有
#define CONCAT(x,y) x##y
#define CONCAT2(x,y) CONCAT(x,y)
然后当预处理器看到
CONCAT(a,CONCAT(b,c))
它知道 CONCAT(x,y) 的替换列表是 x##y,所以它将用 a[=85= 替换 x ] 和 y 与 CONCAT(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT(b,c) 吗? a 不是宏,因此无法展开,在替换列表 x##y 中,y 前面有 ##,因此不会对参数 CONCAT(b,c ).所以替换是在没有扩展的情况下完成的,替换列表变成了##CONCAT(b,c),然后在检查更多宏之前,它处理了##并且替换列表变成了aCONCAT(b,c)。
如果预处理器看到
CONCAT2(a,CONCAT2(b,c))
它知道 CONCAT2(x,y) 的替换列表是 CONCAT(x,y),所以它将用 a[ 替换 x =85=] 和 y 与 CONCAT2(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT2(b,c) 吗? a 不是宏,因此无法展开,在替换列表 CONCAT(x,y) 中,y 前面没有#或##,或后跟##,因此 CONCAT2(b,c) 在替换之前完全展开。所以CONCAT2(b,c)展开为CONCAT(b,c),又展开为b##c,不可能再展开,所以y 替换为 b##c。替换列表 x##y 变为 a##b##c,然后变为 ab##c,然后变为 abc,或者变为 a##bc,然后变为 abc。
如果预处理器看到
CONCAT2(a,CONCAT(b,c))
它知道 CONCAT2(x,y) 的替换列表是 CONCAT(x,y),所以它将用 a[ 替换 x =85=] 和 y 与 CONCAT(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT(b,c) 吗? a 不是宏,因此无法展开,在替换列表 CONCAT(x,y) 中,y 前面没有#或##,或后跟##,因此 CONCAT(b,c) 在替换之前完全展开。所以CONCAT(b,c)被展开为b##c,无法进一步展开,所以将y替换为b##c,替换列表 x##y 变为 a##b##c,或者变为 ab##c 然后变为 abc,或者变为 a##bc 然后变为 abc。
如果预处理器看到
CONCAT(a,CONCAT2(b,c))
它知道 CONCAT(x,y) 的替换列表是 x##y,所以它将用 a[=85= 替换 x ] 和 y 与 CONCAT2(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT2(b,c) 吗? a 不是宏,因此无法展开,在替换列表 x##y 中,y 前面有 ##,因此不会对参数 CONCAT2(b,c ).所以替换是在没有扩展的情况下完成的,替换列表变成了##CONCAT2(b,c),然后在检查更多宏之前它处理了##并且替换列表变成了aCONCAT2(b,c).
你可能会想
#define CONCAT2(x,y) CONCAT(x,y)
表示
CONCAT2(x,y) 应与 CONCAT(x, y)
相同
但请记住:
CONCAT(x,y) 的替换列表是 x##y,因为当预处理器看到 CONCAT 的实例时,x 后面跟着## y 前面跟着##宏,它不会在替换前扩展对应于 x 或 y 的参数。但是 CONCAT2(x,y) 的替换列表是 CONCAT(x,y) 并且替换中的 x 和 y 前面都没有 # 或 ## 或后面有 ##,因此当预处理器看到 CONCAT2 宏的实例时,它将在替换之前完全扩展参数中的任何宏。
参数的宏扩展(如果允许)发生在替换之前。因此在 CONCAT2(a,CONCAT(b,c)) 中,CONCAT(b,c) 参数在替换之前被扩展。所以我们得到 CONCAT2(a, b##c) 而不是 CONCAT(a, CONCAT(b,c)).
在学习 'Preprocessor Operators' 时,我在一本书中找到了一个定义:
#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))
工作正常的证明。
如果你有
#define CONCAT(x,y) x##y
#define CONCAT2(x,y) CONCAT(x,y)
然后当预处理器看到
CONCAT(a,CONCAT(b,c))
它知道 CONCAT(x,y) 的替换列表是 x##y,所以它将用 a[=85= 替换 x ] 和 y 与 CONCAT(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT(b,c) 吗? a 不是宏,因此无法展开,在替换列表 x##y 中,y 前面有 ##,因此不会对参数 CONCAT(b,c ).所以替换是在没有扩展的情况下完成的,替换列表变成了##CONCAT(b,c),然后在检查更多宏之前,它处理了##并且替换列表变成了aCONCAT(b,c)。
如果预处理器看到
CONCAT2(a,CONCAT2(b,c))
它知道 CONCAT2(x,y) 的替换列表是 CONCAT(x,y),所以它将用 a[ 替换 x =85=] 和 y 与 CONCAT2(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT2(b,c) 吗? a 不是宏,因此无法展开,在替换列表 CONCAT(x,y) 中,y 前面没有#或##,或后跟##,因此 CONCAT2(b,c) 在替换之前完全展开。所以CONCAT2(b,c)展开为CONCAT(b,c),又展开为b##c,不可能再展开,所以y 替换为 b##c。替换列表 x##y 变为 a##b##c,然后变为 ab##c,然后变为 abc,或者变为 a##bc,然后变为 abc。
如果预处理器看到
CONCAT2(a,CONCAT(b,c))
它知道 CONCAT2(x,y) 的替换列表是 CONCAT(x,y),所以它将用 a[ 替换 x =85=] 和 y 与 CONCAT(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT(b,c) 吗? a 不是宏,因此无法展开,在替换列表 CONCAT(x,y) 中,y 前面没有#或##,或后跟##,因此 CONCAT(b,c) 在替换之前完全展开。所以CONCAT(b,c)被展开为b##c,无法进一步展开,所以将y替换为b##c,替换列表 x##y 变为 a##b##c,或者变为 ab##c 然后变为 abc,或者变为 a##bc 然后变为 abc。
如果预处理器看到
CONCAT(a,CONCAT2(b,c))
它知道 CONCAT(x,y) 的替换列表是 x##y,所以它将用 a[=85= 替换 x ] 和 y 与 CONCAT2(b,c)。唯一的问题是,它会在替换之前扩展 a and/or CONCAT2(b,c) 吗? a 不是宏,因此无法展开,在替换列表 x##y 中,y 前面有 ##,因此不会对参数 CONCAT2(b,c ).所以替换是在没有扩展的情况下完成的,替换列表变成了##CONCAT2(b,c),然后在检查更多宏之前它处理了##并且替换列表变成了aCONCAT2(b,c).
你可能会想
#define CONCAT2(x,y) CONCAT(x,y)
表示
CONCAT2(x,y) 应与 CONCAT(x, y)
相同但请记住:
CONCAT(x,y) 的替换列表是 x##y,因为当预处理器看到 CONCAT 的实例时,x 后面跟着## y 前面跟着##宏,它不会在替换前扩展对应于 x 或 y 的参数。但是 CONCAT2(x,y) 的替换列表是 CONCAT(x,y) 并且替换中的 x 和 y 前面都没有 # 或 ## 或后面有 ##,因此当预处理器看到 CONCAT2 宏的实例时,它将在替换之前完全扩展参数中的任何宏。
参数的宏扩展(如果允许)发生在替换之前。因此在 CONCAT2(a,CONCAT(b,c)) 中,CONCAT(b,c) 参数在替换之前被扩展。所以我们得到 CONCAT2(a, b##c) 而不是 CONCAT(a, CONCAT(b,c)).