开发者

Creating function-like macros

开发者 https://www.devze.com 2022-12-18 05:45 出处:网络
gcc 4.4.2 c89 I have this code snippet that I have to repeat in a lot of my code. I am just wondering is there a way to make it short by using a macro function?

gcc 4.4.2 c89

I have this code snippet that I have to repeat in a lot of my code. I am just wondering is there a way to make it short by using a macro function?

There is the 开发者_如何学运维code I would like to change.

ERR_INFO error_info; /* create error object */
ErrorInfo(&error_info); /* pass the address for it to be filled with error info */
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); /* display the error msg */

And my attempt to create a macro function to use it.

#define DISPLAY_ERR(error_info) ErrorInfo(&error_info) error_info.msg
fprintf(stderr, "And the error is? [ %s ]\n", DISPLAY_ERR); /* display the error

Any suggestions would be most helpful,


If you really want a macro:

#define DISPLAY_ERR(error_info) \
    do \
    { \
        ErrorInfo(&(error_info)); \
        fprintf(stderr, "And the error is? [ %s ]\n", (error_info).msg); \
    } while(0)

You need the do... while(0) because of a good reason.

Then, you call your macro when you want to print the error:

if (error) {
    DISPLAY_ERR(error_info);
    /* more statements if needed */
}

I am assuming that error_info has been defined somewhere. If not, or if you don't want to, then you can change your macro definition and use:

#define DISPLAY_ERR() \
    do \
    { \
        ERR_INFO error_info;
        ErrorInfo(&error_info); \
        fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); \
    } while(0)

if (error) {
    DISPLAY_ERR();
    /* more statements if needed */
}


There's a couple of ways you could do this. You could use the comma operator:

#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info)),(error_info).msg)

...or you could change the ErrorInfo() function so that it's return value is the pointer you pass it:

#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info))->msg)

(and a few more options besides).


Are you trying to create a macro which "returns" a value? In C++ you can use the comma operator , to evaluate the left expression and then return the right expression. You can do the same in C, too.

(foo(var), var.field) // foo(...)is evaluated first,
                      // then second expression is returned

also

DISPLAY(message) // Pass an argument to macro


You need to make it work like a function call, so it can be used anywhere a function call can, except with no value returned. You also need to mark the ends of intermediate lines with a backslash. And the 'do { ... } while (0) idiom is useful in this context:

#define DISPLAY_ERR() do { ERR_INFO error_info; ErrorInfo(&error_info); \
     fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); } while (0)

The error_info variable is local to the block, so you don't have to remember to declare it in the functions where you use the macro (or have it as a file static or, perish the thought, global variable).

Note that this code does not return a value, but it can be used anywhere in a function that a void expression could be used:

if (somefunc() != 0)
    DISPLAY_ERR();
else if (anotherfunc() != 0)
    DISPLAY_ERR();
else
    do_something_useful_after_all();

Etc.

I would still want to make sure I measured the overhead of using a regular function versus having the function-like macro. Used often enough, you might be still be better off with a real function.

0

精彩评论

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