The code is below. The compiler says "Expected a )", but I do not get it: ( and ) are matching. What did I do wrong?
#define CR_SUCCESS 0
#define EXIT_IF_FAILS(varResult, callString) \
(\
varResult = callString; \
if(varResult != CR_SUCCESS) \
{ \
return -1; \
} \
)
int testFunction(int a, int b)
{
return -1;
}
int main()
{
int result;
EXIT_IF_FAILS(result, testFunction(1, 2));
}
CodePudding user response:
Expanding, your main
looks like
int main()
{
int result;
(
result = testFunction(1, 2);
if(result != CR_SUCCESS)
{
return -1;
}
)
}
This is invalid, since you cannot have parentheses around statements.
For some things you might do when you want a macro which acts like a statement, see the C FAQ "What should be done with macros that have multiple lines?"
CodePudding user response:
You should, as a general rule, avoid function-like macros as much as possible, there's very little need to use them in modern C (a). Most can be easily replaced with inline functions, or even non-inline functions if you trust the compiler to do the right thing.
I realise that's not appropriate for your specific use case since you need to exit the current function as part of the macro but I would ask you to think about why you think you need a macro for this case in the first place.
If it's to simply cut down on code lines, you can equally do that without a macro, such as with:
if ((result = testFunction(1, 2)) != CR_SUCCESS) return -1;
That's equally as succinct (in terms of line count) and doesn't require you to go looking for the macro definition to see what's actually happening.
It also doesn't need all the normal faffing about trying to make sure your macros work in all places where they may be used, such as needing to use the do { ... } while (0)
trick to ensure it works inside if
or else
blocks without braces. See this question and its answers for more explanation on that point.
(a) In fact, even non-function-like macros may be better replaced with enumerations (at least those such as a set of mutually exclusive value like error codes). Nowadays, I tend to use #define
only for conditional compilation, on those relatively rare occasions where I need it.
CodePudding user response:
You are always ignoring result
after testing it, so there is no point keeping it. You know it was zero on success. You can change to:
if (testFunction(1, 2) != 0) return -1;
Maybe you add error reporting later, you can write
result = testFunction(1, 2);
if(result != 0) { printf("error %d", result); return -1; }
So let the macro declare result
#define EXIT_IF_FAILS(callString) { int res = callString; \
if(res != 0) { printf("error %d", res); return -1; }}
But you may find this won't save much time at the end and it can cause problems.