C语言中宏定义(#define)时do{}while(0)的价值(转)
C语言中宏定义(#define)时do{}while(0)的价值
最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总结了一下讨论,加上自己的理解,do{...}while(0)的价值主要体现在:
1. 增加代码的适应性
下面的宏定义没有使用do{...}while(0)
#define FOO(x) foo(x); bar(x);
这样宏定义,单独调用不会出现问题,例如:
FOO(100)
宏扩展后变成:
|
1
|
foo(x);bar(x); |
这样调用FOO没有任何问题,但是FOO(x)不能放入控制语句中,例如
|
1
2
3
4
|
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)的价值(转)的更多相关文章
- C语言中宏定义#define 、 typedef 和枚举类型
替换时机 #define :预编译阶段简单替换,编译阶段展开源程序(1.词法扩展==程序生成期间的字符串替换 2.语义扩展==生成特定指令) 枚举常量:编译阶段确定其值 内联函数:编译阶段插入代码 t ...
- c 语言中宏定义和定义全局变量的区别
宏定义和定义全局变量的区别: 1 作用时间不同. 宏定义在编译期间即会使用并替换,而全局变量要到运行时才可以. 2 本质类型不同. 宏定义的只是一段字符,在编译的时候被替换到引用的位置.在运行中是没有 ...
- C语言中宏定义(#define)时do{}while(0)的价值
最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总结了一下讨论,加上自己的理解,do{...}while(0)的价值 ...
- C语言中宏定义(#define)时do{}while(0)
参考链接: http://www.cnblogs.com/fengc5/p/5083134.html 1.用于宏定义, 在该函数可以调用其它的宏,做其它内容的处理
- C语言中宏定义与C++中的内联函数
一,宏定义:在预处理的时候把宏定义的内容替换到代码中,正常编译. 1,无参数宏定义和有参数宏定义 (1)宏定义不能加分号,比如:#define PI 3.24;错的,#define PI 3.24 ...
- c语言中宏定义和常量定义的区别
他们有共同的好处就是"一改全改,避免输入错误"哪两者有不同之处吗?有的. 主要区别就在于,宏定义是在编译之前进行的,而const是在编译阶段处理的 宏定义不占用内存单元而const ...
- c语言中宏定义#和 ##的作用:
转载:http://www.cnblogs.com/cyttina/archive/2013/05/11/3072969.html 看了这篇文章后了解了,但是文章中的例子比较特别,我在这里加个注释好了 ...
- C语言宏定义#define用法
#define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用 ...
- 宏定义#define整理
一.宏定义#define 优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率.代码可以写的通俗易懂.可以提高程序的清晰性.可读性,使于修改移植等. 缺点:宏定义的使用实 ...
随机推荐
- java序列化ClassNotFoundException
简单的想从保存的对象中重新解析出对象,用了逆序列化,可是报错: java.lang.ClassNotFoundException: xxxxxxxxxxxx at java.net.URLClassL ...
- linux上备份Oracle时EXP-00091的错误解决方法
unix/linux上备份Oracle时EXP-00091的错误解决方法 unix/linux上备份数据时的错误解决方法 EXP-00091: Exporting questionable stati ...
- oracle定时备份与删除N天前备份文件
oracle定时备份数据库,以及删除7天前备份的数据. 1.创建存放备份目录: mkdir /home/oracle/data_backup mkdir /home/oracle/log_backup ...
- nodejs的简单服务器程序
下面是参考<Jquery.Jquery UI 及Jquery Mobile>一书中的nodej服务器程序 var http = require('http'), url = require ...
- Tomcat学习笔记 - 错误日志 - NetBeans配置tomcat出错情况总结 -- 尚未授予访问 Tomcat 服务器的权限。请在服务器管理器的 Tomcat 定制器中设置 "manager-script" 角色的正确用户名和口令。 有关详细信息, 请查看服务器日志。
错误描述: 发布时控制台出现: 部署错误: 尚未授予访问 Tomcat 服务器的权限.请在服务器管理器的 Tomcat 定制器中设置 "manager-script" 角色的正确用 ...
- 我的第一个comet长连接例子
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http ...
- js经典代码技巧学习之一:使用三元运算符处理javascript兼容
window.Event = { add: function() { //使用条件表达式检测标准方法是否存在 return document.addEventListener ? function(a ...
- YY语音从4.0版本开始是基于Qt的开发过程,以及碰到的问题
作者:姚冬链接:http://www.zhihu.com/question/21359230/answer/20127715来源:知乎著作权归作者所有,转载请联系作者获得授权. YY语音从4.0版本开 ...
- 关于HTML5 语音搜索的问题
以前语音输入功能虽然没用过,但是看上去很高级的样子,有了智能手机之后,在ios和android中的语音输入,特别是iPhone的Siri,让一切变得如此简单,嘎嘎. 当然我不是在这里要实现如此强悍的功 ...
- iframe父子页面互调方法和属性
1.iframe子页面调用 父页面js函数 子页面调用父页面函数只需要写上window.praent就可以了.比如调用a()函数,就写成: window.parent.a(); 子页面取父页面中的标签 ...