我正在尝试使用类似函数的宏来生成类似对象的宏名称(通常是符号)。以下操作无效,因为__func__
(C99 6.4.2.2-1)会在函数名称周围添加引号。
#define MAKE_AN_IDENTIFIER(x) __func__##__##x
调用MAKE_AN_IDENTIFIER(NULL_POINTER_PASSED)
所需的结果为MyFunctionName__NULL_POINTER_PASSED
。可能还有其他原因导致这种情况无效(例如__func__
字面意义而不是解释,但我可以解决这个问题)但我的问题是什么会提供预定义的宏,如__func__
除外没有引号?我认为这在C99标准中是不可能的,因此有效的答案可能是对其他预处理器的引用。
目前我只是创建了自己的类似对象的宏,并在每个函数作为函数名之前手动重新定义它。显然这是一种可怜的,可能是不可接受的做法。我知道我可以使用现有的cpp程序或库并对其进行修改以提供此功能。 我希望有一个常用的cpp替换提供这个或预处理器库(更喜欢Python),它是为可扩展性而设计的,这样我就可以“配置”它来创建我需要的宏。
我写了上面的内容,试图提供一个简洁明确的问题,但肯定是@Ruud提到的Y. X是......
我正在尝试管理嵌入式系统中报告错误的唯一值。这些值将作为参数传递给(某些)特定函数。我已经使用pycparser编写了一个Python程序来解析我的代码并识别传递给感兴趣的函数的所有符号。它生成一个.h
#define
个文件,保留以前存在的条目的值,注释掉已删除的条目(以避免重用该值并允许重新引入相同的值),为其分配新的唯一编号新标识符,报告格式错误的标识符,并报告任何给定标识符的多次使用。这意味着我可以简单地写:
void MyFunc(int * p)
{
if (p == NULL)
{
myErrorFunc(MYFUNC_NULL_POINTER_PASSED);
return;
}
// do something actually interesting here
}
并且Python程序将为我创建#define MYFUNC_NULL_POINTER_PASSED 7
(或任何下一个可用的数字)以及所有列出的注意事项。我还编写了一组宏,进一步简化了上述内容:
#define FUNC MYFUNC
void MyFunc(int * p)
{
RETURN_ASSERT_NOT_NULL(p);
// do something actually interesting here
}
假设我提供了#define FUNC
。我想使用函数名称,因为它会在很多变化中保持不变(而不是 LINE ),并且对于某人将旧的生成#define
中的值传递给重命名函数本身时生成的新#define
。老实说,我认为我试图“解决”这个“问题”的唯一原因是因为我必须使用C而不是C ++。在工作中,我们编写了相当面向对象的C,因此有很多NULL
指针检查和IsInitialized
检查。由于所有这些基本检查,我有两个行函数变为30(这些宏将这些行减少了五倍)。虽然我确实喜欢疯狂的宏观发展的挑战,但我更愿意避免它们。也就是说,我不喜欢重复自己并将功能代码隐藏在一堆错误检查中,甚至比不喜欢疯狂的宏还要多。
如果你想更好地解决这个问题,请点击。
答案 0 :(得分:1)
Gnu-C有一个__FUNCTION__
宏,但遗憾的是,即使这样也无法按照你要求的方式使用。
答案 1 :(得分:1)
__FUNCTION__
使用编译为字符串文字(我认为在 gcc 2.96 ),但它已经很多年了。现在我们有__func__
,它编译成字符串 array ,而__FUNCTION__
是不推荐使用的别名。 (这种变化有点痛苦。)
但是在 情况下,是否可以使用此预定义宏来生成有效的C标识符(即“删除引号”)。
但您是否可以使用行号而不是函数名作为标识符的一部分?
如果是这样,以下内容将起作用。例如,编译以下5行源文件:
#define CONCAT_TOKENS4(a,b,c,d) a##b##c##d
#define EXPAND_THEN_CONCAT4(a,b,c,d) CONCAT_TOKENS4(a,b,c,d)
#define MAKE_AN_IDENTIFIER(x) EXPAND_THEN_CONCAT4(line_,__LINE__,__,x)
static int MAKE_AN_IDENTIFIER(NULL_POINTER_PASSED);
将生成警告:
foo.c:5:警告:'line_5__NULL_POINTER_PASSED'已定义但未使用
答案 2 :(得分:1)
正如其他人所指出的,没有宏返回(未引用的)函数名称(主要是因为C预处理器没有足够的语法知识来识别函数)。您必须自己明确定义这样一个宏,就像您自己做的那样:
#define FUNC MYFUNC
为避免必须手动执行此操作,您可以编写自己的预处理器以自动添加宏定义。类似的问题是:How to automatically insert pragmas in your program
如果您的源代码具有一致的编码样式(特别是缩进),那么可以使用简单的基于行的过滤器(sed,awk,perl)。最天真的形式:每个函数都以一个不以哈希或空格开头的行开头,并以一个右括号或逗号结束。使用 awk :
{
print $0;
}
/^[^# \t].*[,\)][ \t]*$/ {
sub(/\(.*$/, "");
sub(/^.*[ \t]/, "");
print "#define FUNC " toupper($0);
}
对于更强大的解决方案,您需要一个像ROSE这样的编译器框架。