博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
do {...} while (0) in macros
阅读量:6237 次
发布时间:2019-06-22

本文共 2544 字,大约阅读时间需要 8 分钟。

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.

转载地址:http://hszia.baihongyu.com/

你可能感兴趣的文章
Python之yield生成器
查看>>
ESXI5.5虚拟机还原快照数据恢复处理办法
查看>>
创建docker私有仓库
查看>>
pthread_rwlock_rdlock和“No such file or directory”
查看>>
redhat-5.4故障排除
查看>>
PHP常见漏洞(1)--SQL注入攻击
查看>>
利用Tomcat的用户名和密码构建“永久”后门
查看>>
详解基于Sbo DI API独立程序系统登录的实现
查看>>
闲谈IPv6-典型特征的一些技术细节
查看>>
AJAX验证用户是否存在
查看>>
.NET (C#) Internals: Struct and Class
查看>>
欺骗黑客的一种有效方法
查看>>
通过Hyper-V批量快速复制实验虚拟机的实践思路
查看>>
C#如何开发扫雷游戏
查看>>
C/C++内存问题检查利器—Purify (四)
查看>>
asp.net MVC中怎样让LINQ Designer自动生成的类从别的类继承并调用其基类构造器?...
查看>>
用VMWARE模拟打造通用批量分发安装系统
查看>>
Python 字符串、列表、元组、索引、切片
查看>>
JAVA实现显示指定类型的文件的例子
查看>>
rm -rfi 防止误删除数据
查看>>