C/C++ 宏中 `do { ... } while (0)` 的“零次循环”技巧
【摘要】 1. 问题现象C/C++ 宏只是简单的文本替换,若宏体包含多条语句,替换后极易出现以下两类错误:else 悬空#define FOO(x) stmt1; stmt2;if (cond) FOO(x); // 只有 stmt1 受 if 控制else bar();花括号与分号不匹配#define FOO(x) { stmt1; stmt2; }if (cond) FO...

1. 问题现象
C/C++ 宏只是简单的文本替换,若宏体包含多条语句,替换后极易出现以下两类错误:
-
else 悬空
#define FOO(x) stmt1; stmt2; if (cond) FOO(x); // 只有 stmt1 受 if 控制 else bar(); -
花括号与分号不匹配
#define FOO(x) { stmt1; stmt2; } if (cond) FOO(x); // 展开后多了一个分号,编译错误 else bar();
2. 解决方案:do { ... } while (0)
把宏体包装在 单次执行的 do-while 循环 中:
#define FOO(x) \
do { stmt1; stmt2; } while (0)
- 语义:循环体只执行一次,与
if/else、for、while等结构无缝衔接。 - 语法:
do { ... } while (0);末尾自带分号,用户正常写FOO(x);即可通过编译。
3. 正确展开示例
if (cond)
FOO(x);
else
bar();
展开后:
if (cond)
do { stmt1; stmt2; } while (0);
else
bar();
- 结构完整,无 else 悬空。
- 分号恰好被
while (0);吸收,无多余符号。
4. 为什么不能仅用大括号
#define FOO(x) { stmt1; stmt2; }
- 替换后:
if (cond) { stmt1; stmt2; }; // 多余的分号导致语法错误 else bar(); - 大括号本身不带分号,无法消化用户写下的分号。
5. 使用要点
- 宏体含多条语句、内部变量定义或需要“单语句”语义时,务必使用
do { ... } while (0)。 - 对于只含一条表达式的宏,可省略此技巧,但保持一致性亦可保留。
- 现代 C++ 推荐用
inline函数或模板替代宏;若必须用宏,则遵循此范式。
6. 结论
do { ... } while (0) 是一个 零成本、零副作用 的惯用法,确保宏在任何上下文中表现如一条普通语句。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)