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

时间:2009-10-12 02:42:30

标签: c macros

我想编写一个C宏,其中包含:

int foo() {
  MY_MACRO
}

并将其扩展为:

int foo() {
  _macro_var_foo++;
}

我发现我不能使用__func__,因为它实际上并没有在宏中扩展;它被预处理器视为变量。

有什么方法可以让它发挥作用吗?

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

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

  

标识符__func__应由翻译者隐式声明,如果,   紧跟在每个函数定义的左大括号后面的声明

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

出现,其中function-name是词法封闭函数的名称

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


GCC(4.4.1)手册在第5.43节(函数名称为字符串)中说明:

  

这些标识符[含义__func____FUNCTION____PRETTY_FUNCTION__]不是预处理器宏。在GCC 3.3及更早版本中,仅在C中,__FUNCTION____PRETTY_FUNCTION__被视为字符串文字;他们可以使用   初始化char数组,它们可以与其他字符串文字连接。 GCC   3.4及以后将它们视为变量,如__func__。在C ++中,__FUNCTION____PRETTY_FUNCTION__一直是变量。

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

答案 2 :(得分:1)

您可以使用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

答案 3 :(得分:1)

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

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

我认为你已经知道了这一点,但记录你可以得到你想要的整体结果:

#define MY_MACRO f_dictionary(__func__, ADDONE);

现在,您只需要为其实施f_dictionaryADDONE操作。