最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总结了一下讨论,加上自己的理解,do{...}while(0)的价值主要体现在:

1. 增加代码的适应性

下面的宏定义没有使用do{...}while(0)

#define FOO(x) foo(x); bar(x);

这样宏定义,单独调用不会出现问题,例如:

FOO()

宏扩展后变成:

foo(x);bar(x);

这样调用FOO没有任何问题,但是FOO(x)不能放入控制语句中,例如

if (condition)
FOO(x);
else
...;

经过宏扩展后,变成了

if (condition)
foo(x);bar(x);
else
...;

这样就导致了语法错误,语法错误并不可怕,在编译阶段就能发现,更致命的是他有可能导致逻辑错误,这种错误编译器发现不了,一出这种问题,程序员就抓狂吧。例如:  

if (condition)
FOO(x);

这段代码经过扩展后变成:

if (condition)
foo(x); bar(x);

这样一来,无论condition是true还是false,bar(x)都会被调用。有没有被这煎熬过的兄弟啊?

这时候do{...}while(0)的价值就体现出来了,修改一下FOO的定义

#define FOO(x) do { foo(x); bar(x); } while (0)

这样FOO,放入控制语句中就没有问题了。

也许有人说:把foo(x);bar(x)用大括号括起来不就行了吗?比如这样定义:

#define FOO(x) { foo(x); bar(x); }

再看下面代码:

if (condition)
FOO(x);
else
...;

扩展后:

if (condition)
{foo(x);bar(x);} ; //注意最后这个分号,语法错误
else
...;

照样语法错误;

2.增加代码的扩展性

我理解的扩展性,主要是宏定义中还可以引用其他宏,比如:

#define FOO(x) do{OTHER_FOO(x)} while(0)
这样我们不用管OTHER_FOO是但语句还是符合语句,都不会出现问题

3.增加代码的灵活性

灵活性主要体现在,我们可以从宏中break出来,例如下面的定义:

#define FOO(x)  do{ \
foo(x); \
if(condition(x)) \
break; \
bar(x) \
..... \
} while(0)

C语言中宏定义(#define)时do{}while(0)的价值的更多相关文章

  1. C语言中宏定义#define 、 typedef 和枚举类型

    替换时机 #define :预编译阶段简单替换,编译阶段展开源程序(1.词法扩展==程序生成期间的字符串替换 2.语义扩展==生成特定指令) 枚举常量:编译阶段确定其值 内联函数:编译阶段插入代码 t ...

  2. C语言中宏定义(#define)时do{}while(0)的价值(转)

    C语言中宏定义(#define)时do{}while(0)的价值 最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总 ...

  3. c 语言中宏定义和定义全局变量的区别

    宏定义和定义全局变量的区别: 1 作用时间不同. 宏定义在编译期间即会使用并替换,而全局变量要到运行时才可以. 2 本质类型不同. 宏定义的只是一段字符,在编译的时候被替换到引用的位置.在运行中是没有 ...

  4. C语言中宏定义(#define)时do{}while(0)

    参考链接: http://www.cnblogs.com/fengc5/p/5083134.html 1.用于宏定义, 在该函数可以调用其它的宏,做其它内容的处理

  5. C语言中宏定义与C++中的内联函数

    一,宏定义:在预处理的时候把宏定义的内容替换到代码中,正常编译. 1,无参数宏定义和有参数宏定义 (1)宏定义不能加分号,比如:#define  PI 3.24;错的,#define  PI 3.24 ...

  6. c语言中宏定义和常量定义的区别

    他们有共同的好处就是"一改全改,避免输入错误"哪两者有不同之处吗?有的. 主要区别就在于,宏定义是在编译之前进行的,而const是在编译阶段处理的 宏定义不占用内存单元而const ...

  7. c语言中宏定义#和 ##的作用:

    转载:http://www.cnblogs.com/cyttina/archive/2013/05/11/3072969.html 看了这篇文章后了解了,但是文章中的例子比较特别,我在这里加个注释好了 ...

  8. C语言宏定义#define用法

    #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用 ...

  9. 宏定义#define整理

    一.宏定义#define 优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率.代码可以写的通俗易懂.可以提高程序的清晰性.可读性,使于修改移植等. 缺点:宏定义的使用实 ...

随机推荐

  1. HTTP 无法注册 URL http://+:12345/HelloWcfService/。进程不具有此命名空间的访问权限

    运行的时候却发现出如下问题:HTTP 无法注册 URLhttp://+:12345/HelloWcfService/.进程不具有此命名空间的访问权限(有关详细信息,请参见http://go.micro ...

  2. c++中运算符重载,+,-,--,+=,-=,*,/,*=,/=,

    #include<iostream> #include<stdlib.h> using namespace std; class Complex { public: Compl ...

  3. xsl输出html代码 非闭合

    ``` </div> <div class="row-fluid"> ···

  4. git 配置用户名和邮箱

    在安装了git for windows之后,个人总是忘记配置git config的命令,以此记录一下: 配置用户名和邮箱的命令 git config --global user.name " ...

  5. .Net 两个对像之间的映射

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. 仿百度自动补全jquery

    新建index.html文件,直接复制下面代码到新建的文件index.html里面,用浏览器访问,仅用于参考: <!doctype html><html><meta ch ...

  7. JAXB - Annotations, Annotations for the Schema: XmlSchema

    This annotation can only be used with a package. It defines parameters that are derived from the xsd ...

  8. Spring MVC中如何指定某个类或方法自适配地响应某个HTTP请求?

    方法已经找到,即调用AbstractHandlerMethodAdapter.handle() public final ModelAndView handle(HttpServletRequest  ...

  9. Java编写ArrayBasic制作一个简单的酒店管理系统

    听老师讲了一些ArrayBasic的一些知识,让制作一个酒店管理系统,要求:显示酒店所有房间列表,预订房间.... 经过老师的指导写了一个代码,如下: import java.util.Scanner ...

  10. invalid code signing entitlement的通用暴力解决办法

    1.添加的一台苹果设备为开发机子后,打版本,说profile 没找到,报错 2.上传二进制文件到itunes connect ,报错 3.有时候还什么 appID 无效,报错 烦死他了 我的解决办法, ...