我想编写一个C宏,其中包含:
int foo() {
MY_MACRO
}
并将其扩展为:
int foo() {
_macro_var_foo++;
}
我发现我不能使用__func__
,因为它实际上并没有在宏中扩展;它被预处理器视为变量。
有什么方法可以让它发挥作用吗?
答案 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_dictionary
和ADDONE
操作。