GCC
有一个关于检测的很好的功能,它允许你在每次调用函数时或每次函数返回时调用例程。
现在,我想创建自己的系统,使其可以移植到其他编译器,并允许工具化我想要的功能(可以改变参数的数量),所以我在两种情况下考虑两种情况。我正在考虑制作某种类型的配置文件,它只能通过define子句激活。
#define FUNCT(t,function_name,...) \
(t) function_name(...) { \
(void) *func_pointer = &(function_name); \
start_data(func_pointer, myclock());
#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}
FUNCT(BOOL, LMP, const int prof, const int nmo))
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
RETURN(FALSE);
}
... do more....
RETURN(TRUE);
}
但我无法让它发挥作用。有人可以帮我弄这个吗?或者这是一项艰巨的任务吗?
我想到的其他选择是让函数在没有宏的情况下声明,如果无论如何知道函数指针而不知道它的名字,就像在VB中调用一个Form with Me一样,它是一个通用别名。有可能吗?
答案 0 :(得分:3)
使用gcc -E
调试您的宏。使用您发布的代码:
$ gcc -E t.c
# ... skip stuff ....
(BOOL) LMP(...) { (void) *func_pointer = &(LMP);
start_data(func_pointer, myclock());)
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
{stop_data(func_pointer, myclock()); return (FALSE);};
}
... do more....
{stop_data(func_pointer, myclock()); return (TRUE);};
}
(我添加了一些空格以使其可读。)
你可以立即看到两个问题:函数参数没有像你想象的那样得到扩展,并且在某个地方还有一个额外的)
。
要获取展开的可变参数,请使用__VA_ARGS__
,而不是...
。迷路)
位于呼叫站点。
所以:
#define FUNCT(t,function_name,...) \
(t) function_name(__VA_ARGS__) { \
(void) *func_pointer = &(function_name); \
start_data(func_pointer, myclock());
#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}
FUNCT(BOOL, LMP, const int prof, const int nmo)
if (nmo <= 5 ||
prof > (prof_l / 3)) {
.... do long operations....
RETURN(FALSE);
}
... do more....
RETURN(TRUE);
}
至于这是否值得尝试(变量宏随附C99,并非所有编译器都实现了该标准,并且支持可能因编译器而异),我不确定。您可能最好使用每个编译器的本机分析工具 - 您可以获得更好的结果,希望减少开销。
答案 1 :(得分:1)
在主叫侧而不是功能侧更容易检测功能。宏可以与函数同名。在某处声明你的替换功能
double myfunc_wrapper(int someArg) {
double ret = 0;
// do something before
...
// now call it
ret = (myfunc)(someArg);
// Then do something after
....
return ret;
}
只是确保将()
置于调用本身以确保始终调用函数而不是宏。
然后使用宏“重载”你的函数
#define myfunc(...) mfunc_wrapper(__VA_ARGS__)
有了这个想法,你可以在你所在的编译单元中动态替换你的函数。
答案 2 :(得分:0)
除了Mat之外,使用#define RETURN(x) {...}
:
if (test)
RETURN (TRUE);
else
RETURN (FALSE);
将评估为
if (test)
{...}
; // <syntactical error
else
{...}
;