#define XXX do{ XXX } while(0) 为什么使用
#define XXX do{ XXX } while(0) 为什么使用
时常会遇到一个非常"奇怪的宏定义", rt.(欧西巴...思考不够深刻啊, 皮鞭, 啪啪啪)
近期又遇到这家伙了,Quora上面Love神回答了这个问题, 我也就顶礼膜拜
http://www.quora.com/What-is-the-purpose-of-using-do-while-0-in-macros
这是C语言里面宏定义的时候,不会造成歧义或副作用的一种经常使用技巧.
考虑一下情况
#define foo(x) bar(x); baz(x)
foo(wolf);
常规的,扩展成例如以下代码:
bar(wolf); baz(wolf);
这都还好,没啥问题.可是假设遇到if推断语句了,看看以下的样例.
f (!feral)
foo(wolf);
这就扩展成了以下的形式,(⊙o⊙)看,是不是出现了你不想要粗线的情况捏?
这里if语句仅仅能作用于第一个bar()函数,无法作用于第二个baz().可是这样的方式非常可能不是程序猿的本意.
本意就是把foo单做一个总体嘛~
if (!feral)
bar(wolf); baz(wolf);
等价于例如以下形式
if (!feral)
bar(wolf);
baz(wolf);
离开了 do/while(0)你就别想把宏定义玩的跟函数一样一样的~
假设使用这样的技巧定义宏定义,
#define foo(x) do { bar(x); baz(x); } while (0)
还是这个宏定义,这么用
f (!feral)
foo(wolf);
就变成了例如以下形式.
if (!feral)
do { bar(wolf); baz(wolf); } while (0);
等价于
if (!feral) {
bar(wolf);
baz(wolf);
}
你可能会想,用以下这样的方式,加个{}不就解决这个问题了么?干嘛害的要do{} while(0)?
考虑例如以下情况
#define foo(x) { bar(x); baz(x); }
if (!feral)
foo(wolf);
else
bin(wolf);
这就变成了
if (!feral) {
bar(wolf);
baz(wolf);
};
else
bin(wolf);
注意!这里使得else变成了"臭名昭著的"dangling else.
版权声明:本文博主原创文章,博客,未经同意不得转载。
#define XXX do{ XXX } while(0) 为什么使用的更多相关文章
- Error Domain=ASIHTTPRequestErrorDomain Code=8 "Failed to move file from"xxx/xxx"to"xxx/xxx"
今天真的好高兴呀 我解决了一个折磨了我一周的问题,真的是激动地要哭出来了,为了这个问题,我嘴也烂了,头发抓了一地啊.虽然解决方法,最后还是展现出了“百度”的伟大,但是我还是很开心,在这里我展示一下我的 ...
- C语言中宏定义(#define)时do{}while(0)的价值(转)
C语言中宏定义(#define)时do{}while(0)的价值 最近在新公司的代码中发现到处用到do{...}while(0),google了一下,发现Stack Overflow上早有很多讨论,总 ...
- Springboot 2.x 无法读取yml配置值的问题:Could not resolve placeholder xxx value '${xxx}'
最近在用Springboot2.1 新建demo工程的时候,在DataSourceConfig类中通过 @Value("${spring.datasource.url}") 的方式 ...
- Python中的xxx == xx是否等价于xxx is xxx
先上代码: >>> a = 1 >>> b = 1 >>> a is b True >>> a == b True what? ...
- Python中的xxx+=xxx和xxx=xxx+xxx一些区别及执行过程
预知小知识: Python中的变量与其他语言稍有差异,如a = 10并不是直接在内存中创建一个变量a其值为10,而是在内存中创建一个a这个a指向这个10,在Python中所有牵扯到等号的均不是值赋值, ...
- 模块,import,from xxx import xxx
一,模块 模块就是一个包含了python定义和声明的文件,文件名就是模块的名字加上.py后缀,总体来说,import加载的模块一共分成四个通用的类别: 1,使用python编写的py文件 2,已被变异 ...
- hadoop报错:java.io.IOException(java.net.ConnectException: Call From xxx/xxx to xxx:10020 failed on connection exception: java.net.ConnectException: 拒绝连接
任务一直报错 现象比较奇怪,部分任务可以正常跑,部分问题报错 报错信息如下: Ended Job = job_1527476268558_132947 with exception 'java.io. ...
- Invalid HTTP_HOST header: 'xxx.xx.xxx.xxx:8000'. You may need to add 'xxx.xx' to ALLOWED_HOSTS
Invalid HTTP_HOST header: 'xxx.xx.xxx.xxx:8000'. You may need to add 'xxx.xx' to ALLOWED_HOSTS - buk ...
- 命令“"xxx.exe" xxx”已退出,代码为 n。这些错误是什么意思?(3 / 123 / 9009)
命令“”xxx.exe” xxx”已退出,代码为 n. 我们在 cmd 中输入常见命令的时候,如果命令输入错误或使用错误,cmd 中会提示错误原因,帮助我们定位并解决问题.然而如果相同的命令放到了 V ...
随机推荐
- 响应VC++ 标题栏右边的关闭按钮“红叉”
击标题栏右边的关闭按钮“红叉”时,程序会向窗口发送WM_CLOSE消息,因此可以截取此消息在窗口关系前做一些提示或者是不允许点击时关闭程序 case WM_CLOSE: if (...) { Post ...
- Delphi 类与对象内存结构浅析(三篇)
http://blog.csdn.net/starsky2006/article/details/5497082 http://blog.csdn.net/starsky2006/article/de ...
- ABP中动态WebAPI原理解析
ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类 ...
- uva10480(最小割)
传送门:Sabotage 题意:给定多个城市的网络,每个城市之间的通信有花费,要求使得首都和最大城市之间的通信断掉的最小花费.要求输出任意一组砸掉的边. 分析:跑一遍最大流dinic后,根据最小割定理 ...
- Libevent使用样例,从简单到复杂
转载请注明出处:http://blog.csdn.net/luotuo44/article/details/39670221 本文从简单到复杂.展示怎样使用libevent.网上的很多 ...
- OpenLayers学习笔记4——使用jQuery UI实现測量对话框
OpenLayers学习最好的方式就是跟着其自带的演示样例进行学习,另外对web前端的开发设计要了解,慢慢积累,这样在一般的小项目中应该是足够用了. 本篇參照量測demo实现对话框形式的量測,抛砖引玉 ...
- bzoj 3519: [Zjoi2014] 消棋子 题解
[序言]在大家怀疑的眼光下,我做了一个中午和半个下午.调了一个晚上的题目总算A了! [原题] 消棋子是一个有趣的游戏.游戏在一个r * c的棋盘上进行.棋盘的每一个格 子.要么是空,要么是一种颜色的棋 ...
- Python什么是二次开发的意义?python在.net项目采用
任何人都知道python在.net该项目是做什么的啊? 辅助用途,用作"二次开发"..net站点的话python主要是CGI才用.能够用python编写B/S程序. 解释一下二次开 ...
- 在ASP.NET MVC 中获取当前URL、controller、action(转)
URL的获取很简单,ASP.NET通用: [1]获取 完整url (协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [2]获取 虚拟目录 ...
- ArrayList线程不安全?
ArrayList是线程不安全的,轻量级的.如何使ArrayList线程安全? 1.继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchro ...