Using and returning output in C macro

。_饼干妹妹 提交于 2020-06-24 05:16:10

问题


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 = function(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.


回答1:


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.




回答2:


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);



回答3:


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



回答4:


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.




回答5:


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);


来源:https://stackoverflow.com/questions/3532621/using-and-returning-output-in-c-macro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!