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 优点:一方面可以节省程序的空间上的篇幅,另外,恰当地使用宏定义可提高程序的时间效率.代码可以写的通俗易懂.可以提高程序的清晰性.可读性,使于修改移植等. 缺点:宏定义的使用实 ...
随机推荐
- 利用@media实现IE hack
虽然对IE深恶痛绝,却不能拒绝. 使用@media实现IE hack的方法,以记之. 仅IE6和IE7识别@media screen\9 { .selector { property: value; ...
- OpenCV——肤色检测
一.RGB color space 检测代码如下: void SkinRGB(IplImage* src,IplImage* dst) { //RGB颜色空间 //均匀照明:R>95,G> ...
- Niagara AX连接MySQL数据库
步骤如下 1.安装Niagara AX (3.8.38): 2.安装MySQL(5.6.25):将MySQL\Connector.J 5.1\mysql-connector-java-5.1.35-b ...
- HibernateTemplate类的方法flush()
hibernate的实体都是存储在缓存中的,所以你会发现有的时候当你创建出两个主键相通的实体的时候会报错.正常情况是当你调用save方法的时候,这个实体对象未必已经保存到数据库了,调用close方法的 ...
- Oracle中MERGE语句的使用
Oracle在9i引入了merge命令, 通过这个merge你能够在一个SQL语句中对一个表同时执行inserts和updates操作. 当然是update还是insert是依据于你的指定的条件判断的 ...
- 基于cygwin构建u-boot(一)环境搭建
从本文开始,更系统的描述基于cygwin构建u-boot. 之前<痛苦的版本对齐>系列,对于cygwin环境下Sourcery CodeBench,u-boot-1.1.6的构建有侧面的说 ...
- haproxy之负载均衡算法
backend blance 算法 动态hash的特点 服务器运行时就可进行权重调整,即只需要重新载入配置文件即可,不需要重新启动haproxy 支持慢速启动,即重新恢复的后端 ...
- python读取Excel
import xlrd # 读取Excel文件 workbook = xlrd.open_workbook(r'E:\2015.xls') # 读取Excel的sheet名字 sheet_names ...
- 关于STM32工程的错误,狗血错误。。。..\CMSIS\core_cm3.h(1087): error: #20: identifier "IRQn_Type" is undefined
这件事还是要写一篇博客了,为了后来的人不换致命性的错误 辛辛苦苦写的一个四个不同的引脚不同时钟不同寄存器分别产生四种不同占空比不同周期的信号方波程序超级经典 PS:页尾上传PWM波形产生工程附件供大 ...
- Windows下FFmpeg快速入门 <第二篇>
FFmpeg简介 FFmpeg是什么? FFmpeg是用于录制.转换和流化音频和视频的完整解决方案, 包括 libavcodec ,一套领先的音/视频编解码类库.FFmpeg 在Linux上开发,当可 ...