文档章节

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

robslove
 robslove
发布于 2015/06/14 14:58
字数 442
阅读 65
收藏 3
点赞 0
评论 0

 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
安装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
网络编程之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
__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
ffmpeg:fatal error C1189: #error : missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS

参考文章:https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=15&t=158 fatal error C1189: #error : missing -DSTDCCONSTANTMACROS / #define STDCCONSTANTMACROS fatal error C1189: #err......

zhuweigangzwg
2015/11/12
0
0
C++预定义宏 C++ Predefined Macros

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

涩女郎
2015/08/25
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
circular buffer in Linux kernel

/ See Documentation/circular-buffers.txt for more information. */ #ifndef LINUXCIRCBUFH #define LINUXCIRCBUFH 1 struct circ_buf { char *buf; int head; int tail; }; / Return coun......

ChenQi
2012/03/23
0
0
linux内核编译__devinit错误解决办法

linux kernel3.8以后,把: devinit, devinitdata, devinitconst, devexit, devexitdata, devexitconst 这些都去掉了。 出现的错误: devinit error expected ‘=’ ‘ ’ ‘ ’ ‘asm’ or ‘......

首席贱人官
2014/09/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CoreText进阶(五)- 文字排版样式和效果

CoreText进阶(五)- 文字排版样式和效果 效果 以下是三个设置了不同属性的效果图 第一个设置了文字颜色为红色,字体为16号 第二个设置了文字颜色为灰色,字体为16号,对其为居中 第三个设置...

aron1992
24分钟前
1
0
10.23 linux任务计划cron~10.27 target介绍

crontab命令被用来提交和管理用户的需要周期性执行的任务,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查是...

洗香香
35分钟前
0
0
告警系统主脚本、告警系统配置文件、告警系统监控项目

20.20 告警系统主脚本 告警系统主脚本 main.sh内容 #!/bin/bash#Written by aming.# 是否发送邮件的开关export send=1# 过滤ip地址export addr=`/sbin/ifconfig |grep -A1 "en...

lyy549745
38分钟前
0
0
Don’t Repeat Yourself

在软件工程中,Don’t Repeat Yourself(DRY)是软件开发的原则,旨在减少重复,用抽象代替它,使用数据规范化来避免冗余。 这个原则在维基百科上是说是由Andy Hunt和Dave Thomas《The Pragmat...

woshixin
40分钟前
0
0
搭建webpack项目框架

作者:汪娇娇 时间:2018年6月4日 一、说明 随着业务发展和前端人员的增加,搭建一个通用框架以及制定统一规范就成了必然。对于选型这方面,一开始好像就没考虑其他框架,直接选了webpack。w...

娇娇jojojo
47分钟前
0
0
Java基础——面向对象(内部类)

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 内部类: 1.有名内部类 2.无名内部类 内部类申请...

凯哥学堂
55分钟前
0
0
HttpClient内部三个超时时间的区别

RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(config.connReqTimeout) //从连接池中获取连接的超时时间 ......

1713716445
今天
0
0
每天一个命令SCP

每天一个命令:SCP scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。可能会稍微影响一下速...

河图再现
今天
0
0
cron/chkconfig/systemd/unit/target

linux任务计划 : cron工具 任务计划在运维工作中用到的比较多,大部分系统管理工作都是通过定期自动执行某个脚本来完成。 查看linux中任务计划的配置文件: /etc/crontab [root@yolks-001 ~]...

Hi_Yolks
今天
1
0
ftp攻略

Vsftpd完全攻略(一)ftp原理与vsftp安装:https://www.iyunv.com/thread-44698-1-1.html Vsftpd完全攻略(二)设置匿名用户也支持下载和上传与创建目录:https://www.iyunv.com/forum.php?mo...

寰宇01
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部