do {...} while (0) in macros
If you are a C programmer, you must be familiar with macros. They are powerful and can help you ease your work if used correctly. However, if you don't define macros carefully, they may bite you and drive you crazy. In many C programs, you may see a special macro definition which may seem not so straightforward. Here is one example:
1
2
#define __set_task_state(tsk, state_value) \
do{ (tsk)->state = (state_value); } while(0)
There are many this kind of macros which uses do{...}while(0) in Linux kernels and other popular C libraries. What's the use of this macro? Robert Lovefrom Google(previously worked on Linux kernel development) gives us the answer.
do{...}while(0) is the only construct in C that lets you define macros that always work the same way, so that a semicolon after your macro always has the same effect, regardless of how the macro is used (with particularly emphasis on the issue of nesting the macro in an if without curly-brackets). For example:
1
#define foo(x) bar(x); baz(x)
Later you may call:
1
foo(wolf);
This will be expanded to:
1
bar(wolf); baz(wolf);
This is the expected output. Next let's see if we have:
1
2
if(!feral)
foo(wolf);
The expansion may not be what you expect. The expansion may be:
1
2
3
if(!feral)
bar(wolf);
baz(wolf);
It isn't possible to write multistatement macros that do the right thing in all situations. You can't make macros behave like functions—without do/while(0).
If we redefine the macro with do{...}while(0), we will see:
1
#define foo(x) do { bar(x); baz(x); } while (0)
Now, this statement is functionally equivalent to the former. The do ensures the logic inside the curly-brackets executes, the while(0) ensures that happens but once. Same as without the loop.For the above if statement, it will be :
1
2
if(!feral)
do{ bar(wolf); baz(wolf); } while(0);
Semantically, it's the same as:
1
2
3
4
if(!feral) {
bar(wolf);
baz(wolf);
}
You might rejoin, why not justwrap the macro in curly-brackets? Why also have the do/while(0)logic? For example, we define the macro with curly bracket:
1
#define foo(x) { bar(x); baz(x); }
This is fine for the above if statement, but if we have below statement:
1
2
3
4
if(!feral)
foo(wolf);
else
bin(wolf);
The expanded code will be :
1
2
3
4
5
6
if(!feral) {
bar(wolf);
baz(wolf);
};
else
bin(wolf);
This is a syntax error.
In conclusion, macros in Linux and other codebases wrap their logic in do/while(0) because it ensures the macro always behaves the same, regardless of how semicolons and curly-brackets are used in the invoking code.
do {...} while (0) in macros的更多相关文章
- 用m4 macros创建文本文件
用m4 macros创建文本文件 原文链接: http://ldp.linux.no/linuxfocus/ChineseGB/September1999/article111.html 补充阅读 ...
- ATL and MFC String Conversion Macros
ATL 7.0介绍了一些新的转换类和宏,为现有的宏提供了重要的改进.新的字符串转换类和名称宏的形式是:C 源类型 2[C] 目标类型[EX]其中:•源类型和目标类型描述如下表.• [C]是目标类型必须 ...
- 7、zabbix使用进阶(03)
节知识点: zabbix自动发现 web监控 zabbix自动发现 官网:https://www.zabbix.com/documentation/4.0/zh/manual/discovery/ ...
- Android Mokoid Open Source Project hacking
/***************************************************************************** * Android Mokoid Open ...
- CV_Assert
转:http://blog.csdn.net/ding977921830/article/details/46376847 Checks a condition at runtime and thro ...
- 基于Arduino的音乐动感节奏灯
1.音乐动感节奏灯是个什么东西? 前段时间听音乐觉得无聊,便想着音乐光听也没意思啊,能不能 “看见” 音乐呢?于是谷歌了一番,发现还真有人做了将音乐可视化的东西,那就是音乐节奏灯.说的简单点就是LED ...
- 恶意代码检测工具 -- Mathematics Malware Detected Tools
Mathematics Malware Detected Tools 重要:由于缺少测试数据,部分结论可能不正确.更多更准确的结论,还需要进行大量实验. 概述 mmdt(Mathematics Mal ...
- [Linux][C][gcc][tips] 在头文件中定义变量引发的讨论
概述 本人的原创文章,最先发表在github-Dramalife-note中.转载请注明出处. Define variable(s) in header file referenced by mult ...
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
随机推荐
- Python学习之eventlet.greenpool
该模块提供对 greenthread 池的支持. greenthread 池提供了一定数量的备用 greenthread ,有效限制了孵化 greenthread 过多导致的内存不足,当池子中没有足够 ...
- Linux 中 x86 的内联汇编
工程中需要用到内联汇编,找到一篇不错的文章,趁机学习下. 原文地址:http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/ 如果 ...
- 【C语言】-一维数组
数组: 数组是一系列相同类型的有序数据的集合,数组中的每一个元素都是同一个数据类型,所有元素共用一个名字,用下标来区别数组中的每一个元素. C语言中,数组属于构造数据类型.一个数组中含有多个数组元素, ...
- 虚拟攻防系统 HoneyPot
转载原地址 http://www.2cto.com/Article/200410/9.html Honeypot 是一个故意设计为有缺陷的系统,通常是用来对入侵者的行为进行警报或者 诱骗.传统的 Ho ...
- IntelliJ IDEA 开发工具项目maven管理
今天自己重新部署一下intellij下的项目开发环境,顺便把maven管理项目jar包的方法梳理一下 (1)首先下载apache-maven-3.0.4版本的maven,我自己解压在D:\maven\ ...
- java commons-lang 工具包 逃脱工具 转unicode 及其他
<dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</ar ...
- 【Android】Handler的应用(三):从服务器端分页加载更新ListView
在前面两节中,我们了解了如何从服务器中加载JSON数据. 现在,我们将把服务器中的JSON数据加载更新到ListView. 并且,结合之前博文的 “动态追加分页ListView数据”的相关知识,实现 ...
- 201. Segment Tree Build
最后更新 二刷 08-Jan-2017 一刷忘了什么时候做的,只是觉得这几个题挺好的,一步一步手动构建线段树,最终理解了这个数据结构,并且后面有利用的地方. 其实重要的3个东西题目已经提供了: 1) ...
- 算法之旅,直奔<algorithm>之十七 find_first_of
find_first_of(vs2010) 引言 这是我学习总结 <algorithm>的第十七篇,find_first_of是匹配的一个函数.<algorithm>是c++的 ...
- AngularJS应用的解析
模板(Templates) 模板是您用HTML和CSS编写的文件,展现应用的视图. 您可给HTML添加新的元素.属性标记,作为AngularJS编译器的指令. AngularJS编译器是完全可扩展的, ...