代码之家  ›  专栏  ›  技术社区  ›  Justin L.

我可以在C宏中将uufunc_uuuuuuuuu替换为标识符名称吗?

  •  2
  • Justin L.  · 技术社区  · 15 年前

    我想编写一个C宏,它采用以下方法:

    int foo() {
      MY_MACRO
    }
    

    并将其扩展到:

    int foo() {
      _macro_var_foo++;
    }
    

    我发现我不能用 __func__ 因为它在宏中并没有被扩展;它被预处理器当作变量来处理。

    有什么办法让这个工作吗?

    4 回复  |  直到 15 年前
        1
  •  3
  •   John Kugelman Michael Hodel    15 年前

    预处理器不知道函数,只知道源文件和行号。在那个阶段,它不执行语法分析,只执行文本分析和替换。这就是为什么 __func__ 是一个神奇的变量,而不是像 __FILE__ __LINE__ .

        2
  •  3
  •   Jonathan Leffler    15 年前

    在C99标准中, __func__ 被赋予“预定义标识符”的特殊新类别(见第6.4.2.2节“预定义标识符”):

    标识符 γ函数 译者应含蓄地声明如下: 紧跟在每个函数定义的左大括号之后,声明

        static const char __func__[] = "function-name";
    

    出现,其中函数名是词汇封闭函数的名称

    这意味着它超出了C预处理器的范围,而C预处理器不知道函数边界或函数名。此外,它将扩展为字符串,这使得它不适合嵌入变量名中。


    GCC(4.4.1)手册在第5.43节(函数名作为字符串)中指出:

    这些标识符[含义 γ函数 , __FUNCTION__ __PRETTY_FUNCTION__ ]不是预处理器宏。在一般合同条款第3.3款及之前,仅在C款中, γ函数 _漂亮的功能__ 被视为字符串文本;它们可以被使用 初始化字符数组,它们可以与其他字符串文本连接。海湾合作委员会 3.4然后将其作为变量处理,比如 γ函数 . 在C++中, γ函数 _漂亮的功能__ 一直是变数。

    如果有一种方法可以将函数名干净地放入预处理器中,那么这里的文档很可能交叉引用了它,如果没有定义它的话。

        3
  •  1
  •   DigitalRoss    15 年前

    从技术上讲,你的问题的答案是“是的”,有“某种方式”。但我认为你已经知道了,而且你确实不能在宏预处理器级别处理这个问题。

    当然,总有一种方法,你可能只需要在那台图灵机上放一个很长的磁带。

    我想你已经知道了,但是 为了记录 您可以获得想要的总体结果:

    #define MY_MACRO f_dictionary(__func__, ADDONE);
    

    所以现在,您只需要实现 f_dictionary 和一个 ADDONE 行动起来。

        4
  •  1
  •   DMC    15 年前

    你可以用 token concatenation .

    #define MY_MACRO(baz) _macro_var_##baz++;
    
    #define FUNC_WRAPPER(bar)\
    int bar()\
    {\
        MY_MACRO(bar)\
    }
    
    FUNC_WRAPPER(foo)
    

    输出来自 GCC - E :

    int foo(){ _macro_var_foo++;}
    

    使用可变宏和X宏处理参数列表的版本:

    #define MY_MACRO(baz) _macro_var_##baz++;
    
    #define FUNC_DEF(ret_type,bar,...)\
    ret_type bar(__VA_ARGS__)\
    {\
        MY_MACRO(bar)\
        FUNC_CONTENTS\
    }
    
    #define FUNC_CONTENTS\
        printf("Do some stuff\n", s1, s2);
    FUNC_DEF(int, foo, char *s1, char *s2)
    #undef FUNC_CONTENT