谈谈#define st(x) do { x } while (__LINE__ == -1) 的理解
来源:互联网 发布:语音相似度匹配算法 编辑:程序博客网 时间:2024/05/15 00:02
最近在学习TI 的ZigBee协议栈,其中发现了一个问题:#define HAL_ENTER_CRITICAL_SECTION(x) st( x = EA; HAL_DISABLE_INTERRUPTS(); )#define HAL_EXIT_CRITICAL_SECTION(x) st( EA = x; )其中st(x)应作何解释?#define st(x) do { x } while (__LINE__ == -1)其中:__LINE__ 是个宏,它代表当前代码在源文件的行号,它是大于0的,所以__LINE__ == -1 等同于0,化简为:#define st(x) do { x } while (0)2,do {} while (0)通常用于宏中, 为的是避免如下情况:#define st(x) x那么我们在调用 if (0) st(a = b; b = c;) 时会被解释成if(0) a = b;b = c;可见, b = c会任何时候都执行。
所以有人想到了用 do { } while (0) 来解决这个问题, do {} while 语句是需要分号来结束的, 另外, 现代编译器的优化模块能够足够聪明地注意到这个循环只会执行一次而将其优化掉.综上所述, do { } while(0) 这个技术就是为了类似的宏可以在任何时候使用.
实际上,do{...}while(0)的作用远大于美化你的代码,while(0)的好处在于,在编译的时候,编译器基本都会为你做好优化,把这部分内容去掉,最终编译的结果不会因为这个do while而导致运行效率上的差异。。查了些资料,总结起来这样写主要有以下几点好处:
1、辅助定义复杂的宏,避免引用的时候出错:
举例来说,假设你需要定义这样一个宏:
#define DO_SOMETHING()\ foo1();\ foo2();
这个宏的本意是,当调用DO_SOMETHING()时,函数foo1()和foo2()都会被调用。但是如果你在调用的时候这写:
if(a>0) DO_SOMETHING();
因为宏在预处理的时候会直接被展开,你实际上写的代码是这个样子的:
if(a>0) foo1();foo2();
这就出现了问题,因为无论a是否大于0,foo2()都会被执行,导致程序出错。
那么仅仅使用{}将foo1()和foo2()包起来行么?
我们在写代码的时候都习惯在语句右面加上分号,如果在宏中使用{},代码里就相当于这样写了:“{...};”,展开后就是这个样子:
if(a>0){ foo1(); foo2();};
注意if{};后面的";",如果if后面还有else等语句则编译不会通过。所以,很多人才采用了do{...}while(0);
#define DO_SOMETHING() \ do{ \ foo1();\ foo2();\ }while(0)\ ... if(a>0) DO_SOMETHING(); ...
这样,宏被展开后,才会保留初始的语义。GCC提供了Statement-Expressions用以替代do{...}while(0); 所以你也可以这样定义宏:
#define DO_SOMETHING() ({\ foo1(); \ foo2(); \})
http://www.spongeliu.com/
2、避免使用goto对程序流进行统一的控制:有些函数中,在函数return之前我们经常会进行一些收尾的工作,比如free掉一块函数开始malloc的内存,goto一直都是一个比较简便的方法:
int foo(){ somestruct* ptr = malloc(...); dosomething...; if(error) { goto END; } dosomething...; if(error) { goto END; } dosomething...; END: free(ptr); return 0; }
由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以很多人都不倡导使用,那这个时候就可以用do{}while(0)来进行统一的管理:
int foo(){ somestruct* ptr = malloc(...); do{ dosomething...; if(error) { break; } dosomething...; if(error) { break; } dosomething...; }while(0); free(ptr); return 0; }
这里将函数主体使用do()while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。
3、避免空宏引起的warning
内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏:
#define EMPTYMICRO do{}while(0)
4、定义一个单独的函数块来实现复杂的操作:
当你的功能很复杂,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);,将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。
5、do {}while(0)的简化
#define st(x) do { x } while (__LINE__ == -1)
1, __LINE__ 是个宏,它代表当前代码在源文件的行号,它是大于0的,所以__LINE__ == -1 等同于0,化简为:
#define st(x) do { x } while (0)
2,do {} while (0)通常用于宏中, 为的是避免如下情况:
#define st(x) x
那么我们在调用 if (0) st(a = b; b = c;) 时会被解释成
if(0)
a = b;
b = c;
可见 if 只对a = b;起作用。
0 0
- 谈谈#define st(x) do { x } while (__LINE__ == -1) 的理解
- 谈谈#define st(x) do { x } while (__LINE__ == -1) 的理解
- 谈谈#define st(x) do { x } while (__LINE__ == -1) 的理解
- #define st(x) do { x } while (__LINE__ == -1)
- #define st(x) do { x } while (__LINE__ == -1)的意义(转)
- #define st(x) do { x } while (__LINE__ == -1)及“\”分析
- do { x } while (__LINE__ == -1)
- 【C】do{}while、do{}while(false)、do{}while(__LINE__==-1)使用分析
- cocos2d-x C++的do...while(0)
- Cocos2d-x do{ }while(0);
- x = x.view(x.size(0), -1) 的理解
- 谈谈#define xxxx(x,y) x##y
- Cocos2d-x中关于do{} while(0) 的解释
- cocos2d-x C++的do...while(0)解释
- cocos2d-x C++的do...while(0)另类使用方法
- cocos2d-x C++的do...while(0)解释
- cocos2d-x系列笔记技巧篇(1)---关于do{}while(0)和CC_BREAK_IF的用法
- cocos2d-x C++的do...while(0)另类使用方法-沈大海cocos2d-x教程5
- 【跑会指南】2017年3-5月IT技术会议大合集
- laravel 路由 详解
- Nmon的安装及使用
- OPENGL双缓冲
- Redis操作
- 谈谈#define st(x) do { x } while (__LINE__ == -1) 的理解
- java自动装箱拆箱深入剖析
- Spring Boot整合Mybatis
- 谷歌开源图片压缩算法Guetzli实测体验报告
- 常用mysql命令
- Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
- linux ssh 免密码登录配置
- 并发编程的艺术笔记-(第一章)并发编程的挑战
- 怎么理解锁
原创粉丝点击热门IT博客热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 卡西欧ga100 传祺ga6图片及价格 传祺ga6为什么卖不动 传奇ga4 ga培训 ga唇釉 ga是什么 ga什么意思 ga赤霉素 ga z77 ga g41m es2l ga是什么激素 ga 赤霉素 技嘉 ga ma78gm s2h 赤霉素 ga 卡西欧ga110说明书图解 卡西欧ga100调时间图解 gb 1gb gb等于多少mb 1gb等于多少mb 王怀南回应传闻 1gb流量 新gb男下载地址 蒂姆逆转西西帕斯夺冠 仿宋gb2312 一gb等于多少mb gb什么意思 gb是什么意思 1tb等于多少gb 流量1gb等于多少mb gb2760 gb7718 1gb等于多少m gb等于多少g gb2312 6gb和8gb有什么区别 gb和mb mb和gb gd gd包