cfunctionmacros

Is 'if(1) { } else' safe for 'function-like macros in c?


I have read in some other questions here in the forum why do { } while (0) is good for function-like macros in C. Also, this form provides the break instruction in order to simulate a return statement.

But in those other questions, I never got anything "clear" about if (1) { } else.

I mean, for me, this is almost equal to do { } while (0) with the difference that here we don't have the break statement.

And I guess it’s better than if (1) { } else { } because allows us to use ;.

But I want to ask you, is it really "safe"? Are there any reasons for choosing this over do { } while (0)?


Solution

  • Consider the alternatives you propose:

    #define foo(x) do { /* main part of macro here */ } while (0)
    #define foo(x) if (1) { /* main part of macro here */ } else
    

    Both of these serve the purpose that the macro can be written like a function call:

    foo(x);
    

    Notably, the semicolon ends the statement, so the macro invocation looks like many other C statements. To somebody experienced in C, it looks odd if there is a line without a semicolon, like:

    x = 3;
    foo(x)
    y = 4;
    

    However, consider if somebody does accidentally write the above, perhaps because they knew foo was a macro and thought it was a whole statement by itself. Then the while form becomes:

    x = 3;
    do { /* main part of macro here */ } while (0)
    y = 4;
    

    This generates a compiler error since it is not valid C grammar (barring weird extensions). In contrast, the if form becomes:

    x = 3;
    if (1) { /* main part of macro here */ } else
    y = 4;
    

    This may compile without an error, since the y = 4; becomes part of the else. So, in this respect, the while form is superior since it catches an error that the if form does not.