在C宏中使用和返回输出

时间:2010-08-20 15:59:48

标签: c return-value c-preprocessor

我正在尝试检测一些代码来捕获和打印错误消息。目前我正在使用像这样的宏:

#define my_function(x) \
  switch(function(x)) { \
    case ERROR: \
      fprintf(stderr, "Error!\n"); \
      break; \
  }

通常,我从不捕获函数输出,这很好用。但我发现了一些情况,我还需要function()的返回值。我试过类似下面的内容,但这会产生语法错误。

#define my_function(x) \
  do { \
    int __err = function(x); \
    switch(__err) { \
      case ERROR: \
        fprintf(stderr, "Error!\n"); \
        break; \
    } \
    __err; \
  } while(0)

我可以声明一个全局变量来保存函数的返回值,但这看起来很难看,我的程序是多线程的,所以这可能会导致问题。我希望那里有更好的解决方案。

5 个答案:

答案 0 :(得分:46)

GCC有一个名为statement expressions

的功能

所以如果像

那样定义宏
#define FOO(A) ({int retval; retval = do_something(A); retval;})

您可以像

一样使用
foo = FOO(bar);

答案 1 :(得分:6)

这是相对复杂的代码,没有太多理由在宏中使用它。如果您确实要将其放在头文件中,请将其设为inline(C99)或static(C89)或两者。使用任何合理的编译器,这应该导致与宏相同的效率。

答案 2 :(得分:4)

回复非常晚。但也是如此。我同意内联函数更好,但MACRO确实提供了一些内联函数无法获得的漂亮打印乐趣。我同意@qrdl,如果你稍微重构了你的语句,你确实可以使用语句表达式。以下是它如何使用宏 -

#define my_function(x, y) ({ \
  int __err = 0; \
  do { \
    __err = function(x, y); \
    switch(__err) { \
      case ERROR: \
        fprintf(stderr, "Error!\n"); \
        break; \
    } \
  } while(0); \
  __err; \
})

答案 3 :(得分:2)

抱歉,这是一个编辑...

  1. 我认为你只需要花括号。不需要do..while关键字
  2. 确保反斜杠是每行的最后一个字符(后面没有空格)。
  3. 如果您需要从宏中获取错误值,则只需添加参数
  4. 即可

    像这样:

     #define my_function(x, out) \
          { \
            int __err = function(x); \
            switch(__err) { \
              case ERROR: \
                fprintf(stderr, "Error!\n"); \
                break; \
            } \
            __err; \
            (*(out)) = _err; \
          }
    

    要保留传递引用C范例,您应该以这种方式调用my_function:

    int output_err;
    
    my_function(num, &output_err);
    

    这样,稍后,如果您决定使my_function成为一个真正的函数,则无需更改调用引用。

    顺便说一句,qrdl的“声明表达”也是一种很好的方法。

答案 4 :(得分:-2)

如果函数返回某些内容,则无需声明变量,那么您可以直接获取该值。例如:

#define FOO(A) do_something(A)

这里do_something返回一些整数。然后你可以轻松地使用它:

int a = FOO(a);