【转】linux中do{...} while(0)的解释
在看ldlm的代码过程中遇到了一个很奇怪的问题,有很多宏定义使用了do while(0)这种看起来好像没啥用的代码。然后我就问问师兄,才得知,这种用法很常见,自己又查了一下资料,原来在linux内核代码中经常用到这个东西!现在就将这个东西整理一下。
为什么在内核中碰到很多 #define ... do{...} while(0) ?
有以下几点原因:
1、空语句在编译的时候会出现警告,所以有必要用#define FOO do{ } while(0)
2、给定一个基本块,可以在里面定义局部变量
3、为了能够在条件语句中使用复杂的宏定义。例如下面这段代码:
#define FOO(x) \
printf("arg is %s\n", x); \
do_something_useful(x);
如果这样用:
if (blah == 2)
F00(blah);
将会被展开为:
if (blah == 2)
printf("arg is %s\n", blah);
do_something_useful(blah);
这样,if条件之后包含了printf()语句,而do_something_useful()调用不能按照预期那样工作。而是用do {...} while(0)定义后,就会展开成以下语句:
if (blah == 2)
do{
printf("arg is %s\n", blah);
do_something_useful(blah);
}while(0);
这是我们所期望的。
如果你希望定义一个包含多行语句和一些局部变量的时候. 一般的定义方式只能这样:
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
然而在某些情况下,这样并不能正常工作. 下面是包含两个分支的if语句:
if (x > y)
exch(x,y); // Branch 1
else
do_something(); // Branch 2
但这样却只能展开成单分支的if语句,如下:
if (x > y) { // 单分支if
int tmp;
tmp = x;
x = y;
y = tmp;
}
; // 空语句
else // 错误!!! "parse error before else"
do_something();
问题是由于在语句块后直接加入分号(;)引起的. 解决办法是将语句块放入 do 和 while (0)中间.这样就得到了一条单语句, 而不是被编译器判断为语句块.现在的if语句如下:
if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while(0);
else
do_something();
假设有这样一个宏定义
#define macro(condition) if(condition) dosomething();
现在在程序中这样使用这个宏:
if(temp)
macro(i);
else
doanotherthing();
一切看起来很正常,但是仔细想想。这个宏会展开成:
if(temp)
if(condition) dosomething();
else
doanotherthing();
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。
为了避免这个错误,我们使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。
参考资料
http://blog.csdn.net/chenhu_doc/article/details/856468
http://www.233.com/linux/fudao/20101102/140715235.html
【转】linux中do{...} while(0)的解释的更多相关文章
- linux中shell变量$#,$@,$0,$1,$2的含义解释
linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...
- linux中shell变量$#,$@,$0,$1,$2的含义解释
linux中shell变量$#,$@,$0,$1,$2的含义解释 linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID ...
- 【转】linux中shell变量$#,$@,$0,$1,$2的含义解释
原文网址:http://www.cnblogs.com/fhefh/archive/2011/04/15/2017613.html linux中shell变量$#,$@,$0,$1,$2的含义解释: ...
- 【Shell】linux中shell变量$#,$@,$0,$1,$2的含义解释 && set 关键字使用
linux中shell变量$#,$@,$0,$1,$2的含义解释 摘抄自:ABS_GUIDE 下载地址:http://www.tldp.org/LDP/abs/abs-guide.pdf linu ...
- 浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释
浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释 下面小编就为大家带来一篇浅谈linux中shell变量$#,$@,$0,$1,$2的含义解释.小编觉得挺不错的,现在就分享给 ...
- linux中shell变量$#,$@,$0,$1,$2的含义
linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...
- linux中shell变量$#,$@,$0,$1,$2
linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...
- Linux中shell变量$0,$?等含义
linux中shell变量$#,$@,$0,$1,$2的基本含义: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...
- linux中shell变量$#,$@,$0,$1,$2的含义解释<转>
linux中shell变量$#,$@,$,$,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行的命 ...
随机推荐
- Ubuntu14.04台式机r8169有线网卡驱动问题
由于台式在安装了Ubuntu14.04后插入网线后灯不亮,不能使用有线网. 查找资料发现原来是网卡驱动问题,解决办法如下: 1.查看网卡驱动名称 lspci -v 找到以太网连接的kernel dri ...
- .NET组件控件实例编程系列——5.DataGridView数值列和日期列
在使用DataGridView编辑数据的时候,编辑的单元格一般会显示为文本框,逻辑值和图片会自动显示对应类型的列.当然我们自己可以手工选择列的类型,例如ComboBox列.Button列.Link列. ...
- Java多线程学习(三)
一.线程的异常(续) 在上一篇博文中我们提到了Thread.UncaughtExceptionHandler接口,我们在日常的编写中可以通过实现这一接口来给每一个Thread对象都附着一个异常处理器, ...
- 雾里看花般的迷茫--货运APP
移动互联网正在改变我们的生活方式,各种手机APP充斥着人们的生活,物流行业也不例外.货运APP的出现,对于物流行业是一个提升的机会,也是迈向标准化和专业化的一个有效途径. 经过三十多年的发展,我国物流 ...
- eclipse构建maven+scala+spark工程 转载
转载地址:http://jingpin.jikexueyuan.com/article/47043.html 本文先叙述如何配置eclipse中maven+scala的开发环境,之后,叙述如何实现sp ...
- nodejs学习笔记二:解析express框架项目文件
上一章介绍了如何去创建一个express框架的工程项目,这章介绍一下express框架下的文件和用法解析,上一张我们创建的工程项目结构图如下: models是不属于原工程项目结构,为了实现数据模型后添 ...
- 山东省第七届ACM省赛------Memory Leak
Memory Leak Time Limit: 2000MS Memory limit: 131072K 题目描述 Memory Leak is a well-known kind of bug in ...
- asp值mysql驱动
http://www.sufeinet.com/thread-10278-1-1.html%20http://tool.sufeinet.com/CodePreview/CodeView.aspx?a ...
- Python写一个Windows下的android设备截图工具
界面版 利用python的wx库写个ui界面,用来把android设备的截图输出到电脑屏幕,前提需要安装adb,涉及到的python库也要安装.代码如下: import wx,subprocess,o ...
- 利用wangEditor获取文章格式和内容
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs& ...