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.
精彩评论