为什么使用 do {} while(0) - yanbin's Blog

为什么使用 do {} while(0)

yanbin posted @ 2015年5月17日 23:16 in Programming with tags linux c c++ c/c++ programming , 1276 阅读

有些宏定义含有多行代码,一般使用 do {} while(0) 把代码放在 'do' 和 'while' 之间的 '{}' 中。

#define foorbar(msg, callback) do {\
         struct Task __task = msg_to_task((msg)); \
           if (__task != NULL) { \
              process(__task, (callback)); \
              char *__msg = task_to_msg(__task); \
              if (__msg != NULL) \ {
                 send_msg(__msg); \
                 free(__msg); \
              } \
              destroy_task(__task); \
           } while (0)

这样用的原因是:
1.符合 C/C++ 语法习惯。
每条语句后面都一个';', 而 do {} while 语句后面也要加一个 ';'.

2.避免出现语法错误。
不用 do {} while(0) 把多行代码包起来,在 if else 语句中就会有语法错误,例如:

#define foorbar(a, b) foor((a)); bar((b))
if (something)
  /* 以下有语法错误 */
  foorbar(3, 2);
else
  // do something

仅仅使用 '{}' 把多行代码包起来,如果在调用宏之后加 ';', 也会有语法错误。

#define foorbar(a, b) {\
           foor((a)); bar((b));\
       }
foorbar(3, 2); // 此处有语法错误

/* 编译器提示:
 * error: expected ‘;’ before ‘}’ token
 * 如果不加 ';', 不会有语法错误但是这样不符合 C/C++ 的语法习惯
 */

3.do {} while(0) 可以根据条件跳出执行。

#define foorbar() do {\
        struct condition __cond; \
        if (__cond.wait_cond()) \
           break; // 条件发生退出执行 \

        // 条件没有发生 do something 
      } while(0)

 

4.私以为 do {} while(0) 可以保证代码执行并且只执行一次。

5.需要注意的地方。
(a)宏定义时用 '\' 连接多行语句;
(b)宏定义中定义变量,注意与外部变量名字冲突,不然原本希望用外面的变量,却用了新定义的变量。
(c)有些编译器会优化掉 do {} while(0); 直接展开 '{}' 内的代码, 如(b)所描述,此时会出现语法错误。
   FIXME: 如果内部有 'break' 并且 'break' 的执行依赖运行时条件,编译器就不会优化掉 do {} while(0); 了。
举例:

#define foorbar() do {\
        struct condition cond; \
        if (cond.wait_cond()) \
           break; // 条件发生退出执行 \

        // 条件没有发生 do something 
      } while(0)

struct condition cond;
// do something
foobar(); // 到底用的是哪一个 cond?
#define foorbar(a, b) do {\
         const char *something = get_something(a, b); \
      } while(0)

const char *something;
// do something

foorbar(3, 9); // 如果编译器优化掉了 do {} while(0); 这里有语法错误。

 

感谢 老猫,mike2,MovableType@源赖朝 三位网友。

参考:
do { … } while (0) — what is it good for?
do{}while(0) 的作用



 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter
Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee