Multi-Line Macros in C

Every once in a while you need to use a multi-line macro in C.  Typically this is because you’re doing something like inlining, but for whatever reason inlining isn’t particle/portable.  I’ll first give you the template for doing this correctly, then explain why.

Let’s say you want to have a macro run_and_test() and you want it to execute run() and test().  The correct form then is this:

#define run_and_test()   do { run(); test(); } while(0)  /* Note: no ending semi-colon */

Explaination

The beginning C student may start out with something like this:

#define run_and_test()   run(); test();

But clearly there’s a problem here when used for example in a while loop.  A line like this:

while( x– ) run_and_test()

Will be expanded to:

while(x–) run();

test();

Clearly this is not what we want.

The next thing you might think is to put braces around like so:

#define run_and_test()   { run(); test(); }

But this now has a problem in the case of nested if’s:

if( condition1 )

if ( condition2 )

run_and_test();

else

something2();

Everything appears okay, doesn’t it?  However, upon closer inspection, the semi-colon will cause some unintended consequences:

if( condition1 )

if( condition2 )

{ run(); test(); }; /* this semi-colon breaks things*/

else

something2();

While normally, empty statements in C are valid, the semi-colon after run_and_test(); will now actually be a syntax error.  You might argue that you should just use run_and_test() without a semi-colon.  Perhaps even put it in all caps, like RUN_AND_TEST() to ensure the user is aware of this requirement.  However, this special condition is difficult for developers specifically because it is very “un-C-like”.

The thing that solves all these conditions, however, is to place the multiple lines in a do { } while(0) block as shown above.  The while(0) ensures the statement gets executed only once.  However, the lack of the semi-colon enforces the typical usage pattern by the developer.

Depending on your macro, the developer may still have to know it’s a macro, as there may be side effects, especially if your macro supports arguments.  But at least this is one less thing he has to be aware of.

Leave a Reply

Your email address will not be published. Required fields are marked *