【问题标题】:Nested ## operator in C PreprocessorC预处理器中的嵌套##运算符
【发布时间】:2014-12-04 17:40:12
【问题描述】:

案例一)

#define CONCATENATE(x,y) x##y

CONCATENATE(a,CONCATENATE(b,c))给出aCONCATENATE(b,c)。

案例2)

 #define CONCATENATE(x,y) x##y
 #define CONCATENATE2(x,y) CONCATENATE(x,y)

CONCATENATE2(a,CONCATENATE2(b,c)) 给出 abc。

为什么 case 1 不起作用? 案例 2 呢?
请按步骤说明。

【问题讨论】:

  • 您的意思是第二个用例是:CONCATENATE2(a, CONCATENATE2(b, c))
  • @RSahu 是的,我做了,我相应地编辑了问题。感谢您的提醒。

标签: c macros c-preprocessor string-concatenation


【解决方案1】:

GCC 文档是这样解释的:

宏参数在宏扩展之前是完全宏扩展的 替换为宏体,除非它们被字符串化或粘贴 与其他令牌

(强调)

另一方面,##(标记粘贴)运算符的操作数在粘贴在一起之前不会进行宏扩展。所以,给定

CONCATENATE(a,CONCATENATE(b,c))

预处理器在扩展外部宏的主体之前不会扩展CONCATENATE(b,c),因为它是## 的操作数。预处理器会在重新扫描以扩展更多宏之前执行令牌粘贴,所以

a ## CONCATENATE(b,c)

变成

aCONCATENATE(b,c)

在重新扫描之前,没有宏aCONCATENATE(但如果有,那么it会被扩展)。

另一方面,与

CONCATENATE2(a,CONCATENATE2(b,c)),

参数CONCATENATE2(b,c)不是##(或#)运算符的操作数,因此在替换到宏体之前先展开,最终产生

CONCATENATE(a, bc)

作为外部宏的第一个扩展。重新扫描以进行进一步扩展,产生

abc

【讨论】:

    【解决方案2】:

    当以自引用方式(或循环方式)使用宏时,就像 CONCATENATE 一样,它们不会递归扩展。这就是为什么:

    CONCATENATE(a,CONCATENATE(b,c)) 给出aCONCATENATE(b,c)

    第二种情况,CONCATENATE2的扩展是在CONCATENATE处理完之后进行的。因此,您会得到正确的输出。

    宏的自引用用法在大多数情况下都可以正常工作。例外是令牌粘贴和字符串化。

    例如,如果您有:

    #define #define foo(x) int x
    

    那么,

    foo(foo(x));
    

    扩展到:

    int int x;
    

    如果你有:

    #define STR(y) #y
    

    那么,

    STR(STR(abcd));
    

    扩展到:

    "STR(abcd)";
    

    更多细节:

    https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

    https://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification

    How does the C preprocessor handle circular dependencies?

    【讨论】:

    • 问题不在于字符串化,而在于令牌粘贴。
    • @JohnBollinger,字符串化只是使用两层宏实现正确的宏扩展和token粘贴的一个例子。
    • 好的,但答案仍然是错误的:自引用宏是宏名称出现在其定义中而不是其参数中的宏。它可以通过参数进行递归,可以很容易地进行测试。
    • @JohnBollinger,我没有说宏是自引用的。我说它是以自我参照的方式使用的。
    • 确实,当宏的名称出现在其定义中时,那些明显的自引用不会被扩展。但是,当宏 argument 包含对被调用宏的引用时,该规则不适用。通常在这些情况下,论点是扩展的。示例:给定 #define foo(x) int xfoo(foo(x)) 扩展为 int int x,而不是 int foo(x)。试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2015-03-29
    • 1970-01-01
    相关资源
    最近更新 更多