开发者

Using and returning output in C macro

I'm trying to instrument some code to catch and print error messages. Currently I'm using a macro somethng like this:

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

Normally, I never capture the function output and this works fine. But I've found a couple cases where I also need the return value of function(). I tried something like the following, but this produces a syntax error.

#define my_function(x) \
  do { \
    int __err = funct开发者_如何学JAVAion(x); \
    switch(__err) { \
      case ERROR: \
        fprintf(stderr, "Error!\n"); \
        break; \
    } \
    __err; \
  } while(0)

I could declare a global variable to hold the return value of the function, but that looks ugly and my program is multithreaded, so that's likely to cause problems. I'm hoping there's a better solution out there.


GCC has a feature called statement expressions

So if define macro like

#define FOO(A) ({int retval; retval = do_something(A); retval;})

then you will be able to use it like

foo = FOO(bar);


This is relatively complicated code, there is not much reason to have it in a macro. Make it inline (C99) or static (C89) or both if you really want to place it in a header file. With any reasonable compiler this then should result in the same efficiency as a macro.


A very late reply. But none the less. I agree inline functions are better but MACROs do offer some pretty printing fun you can't get with inline functions. I agree with @qrdl that you can indeed use statement expressions had you restructured your statements a bit. Here is how it would work with a macro -

#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; \
})


Sorry, this is an edit...

  1. I think you just need the curly braces. No need for the do..while keywords
  2. Make sure that the backslashes are the last characters on each line (no space after).
  3. If you need to get the err value out of the macro, you can just add a parameter

Like so:

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

To preserve the pass-by-reference C paradigm, you should call my_function this way:

int output_err;

my_function(num, &output_err);

This way, later, if you decide to make my_function a real function, you don't need to change the call references.

Btw, qrdl's "Statement Expressions" is also a good way to do it.


there is no need to declare variable if your function is returning something then you can directly get that value. For example:

#define FOO(A) do_something(A)

Here do_something returns some integer. Then you can easily use it like:

int a = FOO(a);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜