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的更多相关文章

  1. 用m4 macros创建文本文件

    用m4 macros创建文本文件   原文链接: http://ldp.linux.no/linuxfocus/ChineseGB/September1999/article111.html 补充阅读 ...

  2. ATL and MFC String Conversion Macros

    ATL 7.0介绍了一些新的转换类和宏,为现有的宏提供了重要的改进.新的字符串转换类和名称宏的形式是:C 源类型 2[C] 目标类型[EX]其中:•源类型和目标类型描述如下表.• [C]是目标类型必须 ...

  3. 7、zabbix使用进阶(03)

    节知识点: zabbix自动发现 web监控 zabbix自动发现   官网:https://www.zabbix.com/documentation/4.0/zh/manual/discovery/ ...

  4. Android Mokoid Open Source Project hacking

    /***************************************************************************** * Android Mokoid Open ...

  5. CV_Assert

    转:http://blog.csdn.net/ding977921830/article/details/46376847 Checks a condition at runtime and thro ...

  6. 基于Arduino的音乐动感节奏灯

    1.音乐动感节奏灯是个什么东西? 前段时间听音乐觉得无聊,便想着音乐光听也没意思啊,能不能 “看见” 音乐呢?于是谷歌了一番,发现还真有人做了将音乐可视化的东西,那就是音乐节奏灯.说的简单点就是LED ...

  7. 恶意代码检测工具 -- Mathematics Malware Detected Tools

    Mathematics Malware Detected Tools 重要:由于缺少测试数据,部分结论可能不正确.更多更准确的结论,还需要进行大量实验. 概述 mmdt(Mathematics Mal ...

  8. [Linux][C][gcc][tips] 在头文件中定义变量引发的讨论

    概述 本人的原创文章,最先发表在github-Dramalife-note中.转载请注明出处. Define variable(s) in header file referenced by mult ...

  9. ZAM 3D 制作简单的3D字幕 流程(二)

    原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...

随机推荐

  1. MVC3.0在各个版本IIS中的部署

    概述: 最近在做一个MVC 3的项目,在部署服务器时破费了一番功夫,特将过程整理下来,希望可以帮到大家! 本文主要介绍在IIS5.1.IIS6.0.IIS7.5中安装配置MVC 3的具体办法! 正文: ...

  2. CentOS 7 安装 PyCharm for python

    下载链接:http://www.jetbrains.com/pycharm/ 如果只是为了开发python,这个免费版的应该已经够了. 今天讲的是怎么在CentOS7下面安装 pycharm: 下载完 ...

  3. 1.1……什么是3G

    移动通信技术的发展 第一代移动通信技术(1st - Generation),只能进行语音通话. 第二代移动通信技术(2nd - Generation),可以收发短信.可以上网,但速度只有几十Kbps, ...

  4. nodejs 5.2.0文档自翻译——Path模块

    模块方法概览 Path path.basename(p[, ext]) path.delimiter path.dirname(p) path.extname(p) path.format(pathO ...

  5. cocosbuilder学习汇总

    目前与cocos2d-x-2.14版本对应的cocosbuilder版本为cocosbuilder-3,目前为alpha-5.稳定版本为cocosbuilder2.1,但与cocos2d-x不匹配(C ...

  6. Java ArrayList Sort

    Collections.sort(hits_list, new Comparator<ScoreDoc>(){ @Override public int compare(ScoreDoc ...

  7. 红包算法思考和总结 -- by jason.zhi

    参考: http://mp.weixin.qq.com/s?__biz=MzI2NjA3NTc4Ng==&mid=402360599&idx=1&sn=69318b235e0e ...

  8. NodeJS学习:爬虫小探补完计划

    说明:本文在个人博客地址为edwardesire.com,欢迎前来品尝. 书接上回,我们需要修改程序以达到连续抓取40个页面的内容.也就是说我们需要输出每篇文章的标题.链接.第一条评论.评论用户和论坛 ...

  9. openstack 云平台API

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABVYAAAKrCAIAAACV8EEMAAAgAElEQVR4nOydeVgUaZ7n/W9299nd7n

  10. Java transient、Volatile关键字

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...