在C宏中使用和返回输出

Mic*_*ior 13 c return-value c-preprocessor

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

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

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

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

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

qrd*_*rdl 56

GCC有一个称为语句表达式的功能

所以如果定义宏像

#define FOO(A) ({int retval; retval = do_something(A); retval;})
Run Code Online (Sandbox Code Playgroud)

你可以使用像

foo = FOO(bar);
Run Code Online (Sandbox Code Playgroud)

  • 基本上,这就是我试图做的。我认为@Jens是对的,内联函数更适合我的需求。 (2认同)

Jen*_*edt 10

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

  • 内联函数的另一个有用的功能是不能扩展`__FILE__`和`__LINE__`宏来生成错误实际发生的错误消息.另外,我个人找到了答案,告诉人们不要做他们要求无益的事情,因为他们没有真正回答这个问题.如果您回答问题,请回答问题.对问题的任何评论应该在问题得到解答后才能发表,或者只是评论. (6认同)
  • 不幸的是,内联函数无法执行宏可以执行的一些操作,例如连接标识符(例如,我正在使用的某些生成代码中的“ FOO ## _size”)。否则,请使用内联函数。 (2认同)

小智 5

一个很晚的答复。但是仍然如此。我同意内联函数更好,但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; \
})
Run Code Online (Sandbox Code Playgroud)

  • 边做边没用吗? (4认同)
  • `({ ... })` 在任何编译器中都可以工作吗?是 GNU C 扩展 https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html (2认同)