0

GCC有一个关于检测的很好的特性,它可以让你在每次调用函数时调用例程,或者每次函数返回时。

现在,我想创建自己的系统以使其可移植到其他编译器,并允许工具化我想要的功能(参数数量可能会有所不同),所以我在两种情况下都考虑了两个宏。我正在考虑制作某种配置文件,它只能通过定义子句激活。

#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 时一样,它是一个通用别名。是否可以?

4

3 回答 3

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 附带可变参数宏,并非所有编译器都实现该标准,并且支持可能因编译器而异),我不确定。使用每个编译器的本机分析工具可能会更好 - 你会得到更好的结果,希望更少的开销。

于 2012-08-08T14:59:18.427 回答
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__)

有了这个想法,您可以在您感兴趣的编译单元中动态替换您的函数。

于 2012-08-08T15:17:51.660 回答
0

除了 Mat 之外,使用还有一个人体工程学问题#define RETURN(x) {...}

if (test)
  RETURN (TRUE);
else
  RETURN (FALSE);

将评估为

if (test)
  {...}
;           // <syntactical error
else
  {...}
;
于 2012-08-08T15:11:37.290 回答