我可以将__func__替换为C宏中的标识符名称吗?
我想写一个C宏,它采用这个:
int foo() { MY_MACRO }
并将其扩展为:
int foo() { _macro_var_foo++; }
我发现我不能使用__func__
,因为它实际上并没有在宏中扩展; 它被预处理器像变量一样对待。
有没有办法让这个工作?
预处理器不知道函数,只知道源文件和行号。 在那个阶段,它不执行语法分析,只进行文本分析和替换。 这就是为什么__func__
是一个神奇的变量,而不是像__FILE__
和__LINE__
这样的神奇宏。
在C99标准中, __func__
被赋予一个特殊的新类别“预定义标识符”(在第__func__
节预定义标识符中):
标识符
__func__
应由翻译器隐式声明,就像紧跟在每个函数定义的__func__
大括号后面的声明一样static const char __func__[] = "function-name";
出现了,其中function-name是词法封闭函数的名称
这意味着它超出了C预处理器的范围,它不知道函数边界或函数名称。 此外,它将扩展为字符串,这使得嵌入变量名称不合适。
GCC(4.4.1)手册在5.43节(函数名称为字符串)中说明:
这些标识符[含义
__func__
__FUNCTION__
,__PRETTY_FUNCTION__
和__PRETTY_FUNCTION__
]不是预处理器宏。 在GCC 3.3及更早版本中,仅在C中,__FUNCTION__
和__PRETTY_FUNCTION__
被视为字符串文字; 它们可以用于初始化char数组,它们可以与其他字符串文字连接。 GCC 3.4及更高版本将它们视为变量,如__func__
。 在C ++中,__FUNCTION__
和__PRETTY_FUNCTION__
一直是变量。
如果有一种方法可以将函数名称干净地放入预处理器中,那么如果它没有定义它,那么这里的文档很可能会交叉引用它。
从技术上讲,你的问题的答案是“是”,有“某种方式”。 但我认为你已经知道了,而且在宏预处理器级别你无法处理这个问题。
当然,总有一种方法,你可能需要在图灵机上使用一个非常长的磁带。
我想你已经知道了,但是为了记录你可以得到你想要的整体结果:
#define MY_MACRO f_dictionary(__func__, ADDONE);
所以现在,您只需要为它实现f_dictionary
和ADDONE
操作。
您可以使用令牌连接执行此操作。
#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