代码之家  ›  专栏  ›  技术社区  ›  redtuna

C预处理器魔术

  •  3
  • redtuna  · 技术社区  · 14 年前

    DECLARE(x)
    

    int _DECLARED_VARIABLE_x_LINE_12
    

    如果声明在输入源的第12行。我试图使用##标记粘贴命令和 __LINE__ __线路__

     #define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
    
    4 回复  |  直到 10 年前
        1
  •  9
  •   Jonathan Leffler    14 年前

    在这种情况下,通常的技巧是使用第二个宏。但是,这似乎不适用于GCC(MacOS X 10.6.4上的4.5.1),需要第三级宏:

    #define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
    
    #define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
    #define DECLARE41(x, line) DECLARE42(x, line)
    #define DECLARE40(x) DECLARE41(x, __LINE__)
    
    int DECLARE(y);
    int DECLARE40(c) = 129;
    

    # 1 "magicvars.c"
    # 1 "<built-in>"
    # 1 "<command-line>"
    # 1 "magicvars.c"
    
    
    
    
    
    
    int _DECLARED_VARIABLE_y_LINE___LINE__;
    int _DECLARED_VARIABLE_c_LINE_8 = 129;
    

    我也很想知道,在你创建了这些变量之后,你将如何引用它们。


    #define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
    
    #define DECLARE11(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
    #define DECLARE10(x) DECLARE11(x, __LINE__)
    
    #define DECLARE23(line) _LINE_ ## line
    #define DECLARE22(x) _DECLARED_VARIABLE_ ## x
    #define DECLARE21(x, line) DECLARE22(x) ## DECLARE23(line)
    #define DECLARE20(x) DECLARE21(x, __LINE__)
    
    #define DECLARE32(line) _LINE_ ## line
    #define DECLARE31(x, line) _DECLARED_VARIABLE_ ## x ## DECLARE32(line)
    #define DECLARE30(x) DECLARE31(x, __LINE__)
    
    #define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
    #define DECLARE41(x, line) DECLARE42(x, line)
    #define DECLARE40(x) DECLARE41(x, __LINE__)
    
    
    int DECLARE(y);
    int DECLARE10(z) = 12;
    int DECLARE20(a) = 37;
    int DECLARE30(b) = 91;
    int DECLARE40(c) = 129;
    

    找出那些不工作的人为什么不工作。不过,他们确实让我找到了可行的答案。(我注意到sunc编译器在相同的输入上产生的结果与GCC基本相同。)

        2
  •  7
  •   AnT stands with Russia    14 年前

    预处理器删除 ## 正在尝试查找用于递归替换的其他宏。这意味着你提到 __LINE__ “粘”到宏的其余部分 它有机会被公认为 __线路__

    因此,如果要将行号嵌入到宏中,除了通过宏参数传递行号外,别无选择

    #define DECLARE_(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
    #define DECLARE(x) DECLARE_(x, __LINE__)
    

    这将正式解决你最初宏定义中的直接问题。

    ## 替换为相应的参数值 没有 参数值中的递归宏展开。即。 L 将替换为 __线路__ __线路__ 先到实际行号。

    ,需要在宏定义中引入另一个“间接层次”

    #define DECLARE__(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
    #define DECLARE_(x, L) DECLARE__(x, L)
    #define DECLARE(x) DECLARE_(x, __LINE__)
    

    在这种情况下,处理时 DECLARE_(x, L) 宏,预处理器将处理 递归地:首先用 __线路__ __线路__ 实际行号。 DECLARE__

        3
  •  1
  •   Community CDub    8 年前

    有一个问题 __LINE__ Here is a reference to it. 不过,这个问题已经有几年历史了。如果这个问题解决了,那么 Jonathan Leffler's solution 会很好的。

        4
  •  0
  •   Agnius Vasiliauskas    14 年前

    1. 粘贴之前,##运算符的操作数不会展开。