Why is this code using a do{}while(0) in a macro?

The other answers have already explained the issue with using plain {...} for this purpose. Again, if you use plain {...} inside the macro and then just habitually follow your macro invocation with ;, as in

WRITE_INTERRUPT_MASK(0x42);

the compiler will see it as two consecutive statements: a compound statement followed by an empty statement

{ ... } // <- first statement: macro body
;       // <- second statement: empty statement

Empty statement is a no-op, so this will work as long as you are using it somewhere in the middle of a plain linear sequence of statements. But if you attempt using it in an if-else statement, like this

if (condition)
  WRITE_INTERRUPT_MASK(0x42);
else
  /* whatever */;

thing will start falling apart. The compiler will treat only the {...} statement as par of the if, while the ; (empty statement) will be considered an independent statement that follows if. This will make the else part orphaned. The code will not compile.

This code

do
  WRITE_INTERRUPT_MASK(0x42);
while (condition);

will not compile for exactly the same reason.

You can work around this problem by either always remembering to omit the ; in such cases

if (condition)
  WRITE_INTERRUPT_MASK(0x42)
else
  /* whatever */;

or by wrapping your macro invocation into an extra pair of {...} in such cases

if (condition) {
  WRITE_INTERRUPT_MASK(0x42);
}
else
  /* whatever */;

but all this is exactly what we are trying to avoid. We want a macro that behaves as a good-mannered function and not forces us to watch out for various "special contexts".

And this is where the do-while trick comes in. In case of do-while that trailing ; becomes a part of the same single do-while statement, instead of introducing a second empty statement. This is what makes it work as we want it to.

/r/C_Programming Thread