文档章节

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

共有 人打赏支持
robslove

robslove

粉丝 4
博文 181
码字总数 78325
作品 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
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
03/22
0
0
安装util-macros,make 不成功,make: Nothing to be done for `all'

~/wayland/util-macros-1.19.0$ ./configure --prefix=$WLD checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking f......

Areas
2015/10/06
459
0
__STDC_LIMIT_MACROS 和 __STDC_CONSTANT_MACROS

Question: I see this in the standard C++ libraries for my system, as well as some of the headers in a library I'm using. What are the semantics of these two definitions? Is ther......

长平狐
2013/03/04
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

怎样使用主流缓存更新策略来减少性能消耗?

在互联网项目开发中,缓存的应用是非常普遍了,缓存可以帮助页面提高加载速度,减少服务器或数据源的负载。 一、为什么需要缓存? 一般在项目中,最消耗性能的地方就是后端服务的数据库了。而...

Java干货分享
6分钟前
1
0
杭州云栖大会阿里云放大招,8K远程医疗会诊引关注

大家每天都会照镜子,镜子里的一切都清清楚楚,足可乱真,可是你想过有一天看视频直播就像照镜子么? 这不,在云栖大会的C馆里,8K超高清直播体验馆前异常火爆,在这里,很多参会者都围着有1...

阿里云云栖社区
8分钟前
15
0
C++获取系统盘符极简方法

盘符获取 std::shared_ptr<std::list<wchar_t>> disks(void) {wchar_t data[255];return [&](int length)->std::shared_ptr<std::list<wchar_t>> {auto result = std::make_shared< s......

CHONGCHEN
8分钟前
1
0
Python 操作samba文件服务器

# /usr/bin/env python# -*- coding:utf-8 -*-from smb.SMBConnection import SMBConnectionconn = SMBConnection('root', '123456', 'any', '', use_ntlm_v2 = True)assert conn.......

China丶小可
15分钟前
1
0
vue引入echart.js打包时特别大

link : https://www.cnblogs.com/strinkbug/p/5786222.html 一、i在html中添加script标签如下: <script src="//cdn.bootcss.com/echarts/3.2.2/echarts.simple.min.js"></script> 二、在web......

Js_Mei
19分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部