为什么在宏中使用'do {} while(0)'?

时间:2011-03-18 10:35:52

标签: c macros

  

可能重复:
  Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?

在我的c代码中,我需要使用宏。我使用gcc编译了我的代码。 以下是我的实验:

#define temp(a, b) a++; \
   b++;

foo()
{
  temp(x, y);
}

^^^^^ this will work fine

#define temp(a, b) a++; \
   b++;

foo()
{
  if(z)
     temp(x, y);
  else
    foo();
}

^^^^^ this will not work

#define temp(a, b) { \                                       <<<
   a++; \
   b++; \
   }                                        <<<

foo()
{
   if(z)
     temp(x, y);
   else
     foo();
}

^^^^^ this will also not work

#define temp(a, b)  do { \                                       <<<
   a++; \
   b++; \
   } while(0)                                 <<<

foo()
{
   if(z)
     temp(x, y);
   else
     foo();
}

^^^^^ this will work  :)

3 个答案:

答案 0 :(得分:2)

'do while'可以作为一个声明,并且适合用a终止它;这是你在使用temp之后写的。

其他示例不起作用,因为扩展宏时,生成的代码具有错误的C ++语法,或者并不意味着您的意思。

#define temp(a, b) a++; \
   b++;

foo()
{
  if(z)
     temp(x, y);
  else
    foo();
}

不起作用,因为它扩展为:

foo()
{
  if(z)
     x++;
     b++;
  else
    foo();
}

if或else的主体只允许在C ++中使用一个语句,但你基本上放了两个。

#define temp(a, b) { \
   a++; \
   b++; \
   }

foo()
{
   if(z)
     temp(x, y);
   else
     foo();
}

扩展为:

foo()
{
   if(z)
   {
     a++;
     b++;
   };
   else
     foo();
}

分号;在语言规则之前不允许使用else之前。我得到编译错误“Illegal else without matching if if”

但是,'do-while'版本确实有效。它扩展到:

foo()
{
   if(z)
     do {
       a++;
       b++;
     } while(0);
   else
     foo();
}

这是完全合法的C ++并且具有您想要的行为。 do-while的主体将被执行一次,并且0被视为false并导致执行离开循环。编译器应该能够意识到while条件总是为false,并且会生成有效运行它的机器指令。

答案 1 :(得分:0)

请参阅:“编写多语句宏的最佳方法是什么?” http://c-faq.com/cpp/multistmt.html

答案 2 :(得分:0)

几年前,我写了几篇关于预处理器的文章,包括一些常用的民间传说。 do { ... } while(0)技巧在第二部分中介绍:

http://www.iar.com/website1/1.0.1.0/476/1/

http://www.iar.com/website1/1.0.1.0/477/1/