It's done so that if you forget to add a ; at the end of the macro, it causes an error on compile, as it would if it were a function.
If you made this (admitted useless) macro:
#define DBG(x,y) printf ("Debug output %d\n", x); printf (" %d\n", x+y);
you can call the macro like this:
void someFun ()
{
DBG(10,0)
DBG(11,40)
}
And it will compile perfectly fine.
The do {...} while (0) forces you to include the ; at the end, in case the macro is later turned into a function - which often happens. When this change is made, all of sudden you may have thousands of syntax errors to fix. The way I would define it would be:
#define DBG(x,y) \
do \
{ \
printf ("Debug output %d\n", x); \
printf (" %d\n", x+y); \
} while (0)
Now you must include a ; at the end of the macro. Remember, macros literally replace code during the preprocessor phase.
Now - also consider what would happen if you did this with both macros:
if (x==y)
DBG(x,y);
It would always print the sum of x and y, regardless of what the if evaluated to if you used the first macro shown.
You're probably thinking, that this would fix it:
#define DBG(x,y) {printf ("Debug output %d\n", x); printf (" %d\n", x+y);}
And it would, but you're right back to being able to forget the ';' again.
Clean code isn't necessarily good code, but great code written like garbage will make you think the code sucks. Develop good habits because 5 months down the road, you might have to pull out some code you thought you were done with, and you're going to hate your past self for screwing you over.
Now in your case, the macro wasn't turned into a function, it was simply removed or never populated.