Это сделано для того, чтобы, если вы забыли добавить;в конце макроса он вызывает ошибку при компиляции, как если бы это была функция.
Если вы сделали этот (допустимый бесполезный) макрос:
#define DBG(x,y) printf ("Debug output %d\n", x); printf (" %d\n", x+y);
вы можетевызовите макрос следующим образом:
void someFun ()
{
DBG(10,0)
DBG(11,40)
}
И он будет прекрасно скомпилирован.
do {...} while (0) заставляет вас включить;в конце, в случае, если макрос позже превращается в функцию - что часто случается.Когда это изменение будет сделано, внезапно вы сможете исправить тысячи синтаксических ошибок.Я бы это определил так:
#define DBG(x,y) \
do \
{ \
printf ("Debug output %d\n", x); \
printf (" %d\n", x+y); \
} while (0)
Теперь вы должны включить;в конце макроса.Помните, что макросы буквально заменяют код на этапе препроцессора.
Теперь рассмотрим, что произойдет, если вы сделаете это с обоими макросами:
if (x==y)
DBG(x,y);
Всегда будет выводиться сумма x иу, независимо от того, что вычисляется, если вы использовали первый показанный макрос.
Вы, вероятно, думаете, что это исправит это:
#define DBG(x,y) {printf ("Debug output %d\n", x); printf (" %d\n", x+y);}
И это будет, но вывернулись к возможности забыть ';'снова.
Чистый код не обязательно хороший код, но отличный код, написанный как мусор, заставит вас думать, что код - отстой.Вырабатывайте хорошие привычки, потому что через 5 месяцев вам, возможно, придется вытащить какой-то код, с которым, как вы думали, вы покончили, и вы возненавидите свое прежнее «я» из-за того, что вас обманывают.макрос не был превращен в функцию, он был просто удален или никогда не заполнялся.