C语言在linux内核中do while(0)妙用之法
为什么说do while(0) 妙?因为它的确就是妙,而且在linux内核中实现是相当的妙,我们来看看内核中的相关代码:
#define db_error(fmt, ...) \ do { \ fprintf(stderr, "(error): "); \ fprintf(stderr, fmt, ##__VA_ARGS__); \ } while (0)
这只是个普通的调试信息的输出,有人便会认为,你这不是多此一举吗?去掉do while(0)不一样也实现了吗?其实不然,我们看看例子就清楚了,尽管很简单:
int main(void) { while(0) { printf("hello world\n"); } do { printf("hello world1\n"); }while(0); return 0 ; }
这是一段简单到不能再简单的代码了,但还是要提一下,请看运行结果:
谁都知道第一个while(0)肯定是不会运行的,因为while()括号中的数值等于0,逻辑判定为假,即代码块中的hello world不会运行,但是do while(0)就不一样了,do while(0)即使条件不成立,也会拼了老命的去执行一次!
也就是说,为什么内核代码要这样来做,这是因为内核代码采用do{}while(0);这种结构可以保证无论在什么地方都可以正确的执行一次 ,这就是它用得最妙的地方,否则有时候调试程序的时候,单单的调试语句写了没打印其实是很正常的事情,不知道大家写代码的时候有没有遇到过,反正我是遇到过了,后来就是用这样的一种方法定位到错误点,顺利改正。
代码虽简单,但是用好用精熟练使用不一定什么时候都能想得到,越简单的东西,有时候,适用价值还是很好的!
分享以下我实现的调试输出程序,以后可以拿来当模版开发了:
#include <stdio.h> #include <stdarg.h> //内核代码采用do{}while(0);这种结构可以保证无论在什么地方都可以正确的执行一次 #define db_error(fmt, ...) \ do { \ fprintf(stderr, "(error): "); \ fprintf(stderr, fmt, ##__VA_ARGS__); \ } while (0) #define db_msg(fmt, ...) \ do { \ fprintf(stdout, "(msg): "); \ fprintf(stdout, fmt, ##__VA_ARGS__); \ } while (0) #define db_warn(fmt, ...) \ do { fprintf(stdout, "(warn): "); \ fprintf(stdout, fmt, ##__VA_ARGS__); \ } while (0) #define db_debug(fmt, ...) \ do { \ fprintf(stdout, "(debug): "); \ fprintf(stdout, fmt, ##__VA_ARGS__); \ } while (0) int main(void) { db_error("h\n"); db_warn("e\n"); db_debug("llo\n"); return 0 ; }
运行结果:
调试信息在前,很快就可以知道在什么地方打印的语句,方便DEBUG!迅速找到程序bug的定位!
C语言在linux内核中do while(0)妙用之法的更多相关文章
- go例子(一) 使用go语言实现linux内核中的list_head
package list 代码 package list import ( "fmt" ) // 数据接口 type ElemType interface{} // 节点 type ...
- linux内核中的C语言常规算法(前提:你的编译器要支持typeof和type)
学过C语言的伙伴都知道,曾经比较两个数,输出最大或最小的一个,或者是比较三个数,输出最大或者最小的那个,又或是两个数交换,又或是绝对值等等,其实这些算法在linux内核中通通都有实现,以下的代码是我从 ...
- 嵌入式C语言自我修养 01:Linux 内核中的GNU C语言语法扩展
1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”.说它是C语言吧, ...
- Linux内核中的fastcall和asmlinkage宏
代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...
- C语言之linux内核实现最大公约数算法
最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算. 两个整数的最大 ...
- 调皮的程序员:Linux之父雕刻在Linux内核中的故事
本文内容由公众号“格友”原创分享. 1.引言 (不羁的大神,连竖中指都这么帅) 因为LINUX操作系统的流行,Linus 已经成为地球人都知道的名人.虽然大家可能都听过钱钟书先生的名言:“假如你吃 ...
- Linux 内核中的 GCC 特性
https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...
- linux内核中GNU C和标准C的区别
linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...
- Linux 内核中的 Device Mapper 机制
本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...
随机推荐
- springMVC源码分析--HandlerInterceptor拦截器(一)
对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器,HandlerInterceptor接口给我们提供了3个方法: (1)preHandle: 在执行controll ...
- Android Studio基本配置
主题设置 File→Settings- 添加第三方主题 网址:http://www.ideacolorthemes.org/home/ File→Import Settings- 设置控制台字体大小 ...
- iOS中监控软键盘显示或隐藏的可靠方法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 如果你试图在软键盘的显示或隐藏时去改变的UI界面结构,仅有的方 ...
- Calling LoadLibraryEx on ISAPI filter failed
今天在访问IIS下的站点时莫名奇妙的遇到这个问题Calling LoadLibraryEx on ISAPI filter"C://..." failed,前面引号中的" ...
- C语言一个双向链表的实现
首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下: #ifndef DList_H #define DList_H typedef int Item; typedef struct ...
- 解决android 大图OOM的两种方法
最近做程序中,需要用到一张大图.这张图片是2880*2180大小的,在我开发所用的华为3C手机上显示没有问题,但是给米3装的时候,一打开马上报OOM错误.给nexus5装,则是图片无法出来,DDMS中 ...
- UNIX网络编程——经常使用的套接字选项
1.设置/获取套接字选项 int setsockopt(int socket, int level, int option_name, const void *option_value, sockle ...
- Android的资源类型和存储方式简介-android学习之旅(五十二)
android资源的类型 android资源的存储方式
- 钩子不仅仅是windows给你留的后门
说起钩子(Hook)熟悉windows开发的人应该比较熟悉,例如鼠标钩子.键盘钩子等.用简单的语言描述就是在正常处理流程中安置某个钩子,当执行到安置钩子的地方就将进入指定的钩子函数进行处理,待处理完再 ...
- React Native之Navigator
移动应用很少只包含一个页面.从你添加第二个页面开始,就得考虑如何管理多个页面间的跳转了. 导航器正是为此而生.它可以管理多个页面间的跳转,也包含了一些常见的过渡动画,包括水平翻页.垂直弹出等等. Na ...