I was reverse engineering some code and came across this...
/************************************************************************/
/* */
/* MACRO CHECK_FREAD */
/* */
/* CHECK_FREAD is used to check the status of a file read. It */
/* is passed the return code from read and a string to print out if */
/* an error is detected. If an error is found, an error message is */
/* printed out and the program terminates. This was made into a */
/* macro because it had to be done over and over and over . . . */
/* */
/************************************************************************/
#define CHECK_FREAD(X, msg) if (X==-1) \
{ \
return(DCD_BADREAD); \
}
Basically, the particular set of functions in this file call this whenever they do a (c-read) to check the result for an error. They also have a similar check for EOF... Basically as far as I can tell, they're doing it this way to insert returns on error in the middle of their function in a bunch of places.
e.g.
/* Read in an 4 */
ret_val = read(fd, &input_integer, sizeof(int32));
CHECK_FREAD(ret_val, "reading an 4");
CHECK_FEOF(ret_val, "reading an 4");
if (input_integer != 4)
{
return(DCD_BADFORMAT);
}
/* Read in the number of atoms */
ret_val = read(fd, &input_integer, sizeof(int32));
*N = input_integer;
CHECK_FREAD(ret_val, "reading number of atoms");
CHECK_FEOF(ret_val, "reading number of atoms");
Now I'm just getting back into c/c++ programming, and I never used macro's much in the first place, but is this macro abuse?
I read this... When are C++ macros beneficial?
...and it doesn't sound like any of the kosher examples, so my guess would be "YES". But I wanted to get a more informed opinion rather than just making educated guesses... :)
...errr, wouldn't it be better to use some sort of wrapping?
Because it's not the same. If you put the same thing into a function, you'll have a short function that returns DCD_BADWRITE
if X
equals -1. The macro in question however returns from the containing function. Example:
int foobar(int value) {
CHECK_FREAD(value, "Whatever");
return 0;
}
would expand to:
int foobar(int value) {
if (value == -1) {
return (DCD_BADWRITE);
};
return 0;
}
If, however, it were a function, the outer function (foobar
) would happily ignore the result and return 0.
A macro that looks so much like a function, but behaves differently in a crucial way, is a major no-no IMO. I'd say yes, it is macro abuse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With