文档章节

do {...} while (0) in macros

robslove
 robslove
发布于 2015/06/14 14:58
字数 442
阅读 66
收藏 3

 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:

#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 Love from 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:

#define foo(x)  bar(x); baz(x)

Later you may call:

foo(wolf);

This will be expanded to:

bar(wolf); baz(wolf);

This is the expected output. Next let's see if we have:

if (!feral)
    foo(wolf);

The expansion may not be what you expect. The expansion may be:

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:

#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 :

if (!feral)
    do { bar(wolf); baz(wolf); } while (0);

Semantically, it's the same as:

if (!feral) {
    bar(wolf);
    baz(wolf);
}

You might rejoin, why not just wrap the macro in curly-brackets? Why also have the do/while(0) logic? For example, we define the macro with curly bracket:

#define foo(x)  { bar(x); baz(x); }

This is fine for the above if statement, but if we have below statement:

if (!feral)
    foo(wolf);
else
    bin(wolf);

The expanded code will be :

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.


本文转载自:http://www.pixelstech.net/article/1390482950-do-%7B-%7D-while-%280%29-in-macros

共有 人打赏支持
上一篇: RTTI
下一篇: IOS屏幕旋转
robslove

robslove

粉丝 4
博文 187
码字总数 79008
作品 0
成都
程序员
私信 提问
zabbix使用过程中遇到的问题与解决方法(2)

一、旧版本中很多trigger不能用,比如下面的一个trigger expression是这样的::system.cpu.load[percpu,avg5].avg(5m)}>{$CPU_LOAD_NUM_W_GT_N},其中,CPU_LOAD_NUM_W_GT_N不是具体的数值 ...

yangjingangel
2018/06/26
0
0
HPC Template Library, A Supplement to the STL

Download source Download HTLDocs052 Author: Anthony Daniels Introduction This package is intended to provide the user with threadsafe containers and classes for applications in ......

trident99
2017/12/15
0
0
网络编程之IPv4和IPv6的互通性剩余小知识点(二)

1. IPv6 Address-Testing Macros The first seven macros test the basic type of IPv6 address. The final five macros test the scope of an IPv6 multicast address. 2. 总结 An IPv6 se......

lovestackover
2018/03/22
0
0
RPM build errors: Installed (but unpackaged) fi...

解决方法: 第一种: add those files below %files section To make it build you just add the unpacked files to the list 第二种: 对于安装后的文件会被修改的情况, 利用%config(noreplace......

Start-up
2012/07/06
0
0
C++预定义宏 C++ Predefined Macros

一、ANSI C标准预定义宏 LINE:在源代码中插入当前源代码行号; FILE:在源文件中插入当前源文件名; DATE:在源文件中插入当前的编译日期 TIME:在源文件中插入当前编译时间; STDC:当要求...

涩女郎
2015/08/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Jmeter参数的AES加密使用

在Jmeter日常实践中,大家应该都遇到过接口传参需要加密的情况。以登陆为例,用户名和密码一般都需要进行加密传输,在服务端再进行解密,这样安全系数会更高,但在使用jmeter进行接口测试的时...

程序猿拿Q
23分钟前
2
0
MYSQL 日期函数 Date and Time Functions

Table 12.13 Date and Time Functions Name Description ADDDATE() Add time values (intervals) to a date value ADDTIME() Add time CONVERT_TZ() Convert from one time zone to another ......

_liucui_
30分钟前
2
0
Android代码混淆ProGuard工作原理简介

ProGuard能够对Java类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。    1. 压缩(Shrink): 在压缩处理这一步中,用于检测和删除没有使用的类,字段...

SuShine
32分钟前
1
0
Idea 2018激活

教程地址: https://www.52pojie.cn/thread-781394-1-1.html 亲测可用

一个不正经的程序员
37分钟前
1
0
Android组件化开发实践和案例分享

目录介绍 1.为什么要组件化 1.1 为什么要组件化 1.2 现阶段遇到的问题 2.组件化的概念 2.1 什么是组件化 2.2 区分模块化与组件化 2.3 组件化优势好处 2.4 区分组件化和插件化 2.5 applicatio...

潇湘剑雨
38分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部