Home > Software design >  Why does the compiler say this macro function needs a closing parenthesis?
Why does the compiler say this macro function needs a closing parenthesis?

Time:10-02

The code is below. The compiler says "Expected a )", but I do not get it: ( and ) are matching. What did I do wrong?

enter image description here

#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.

  •  Tags:  
  • c
  • Related