为什么说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)妙用之法的更多相关文章

  1. go例子(一) 使用go语言实现linux内核中的list_head

    package list 代码 package list import ( "fmt" ) // 数据接口 type ElemType interface{} // 节点 type ...

  2. linux内核中的C语言常规算法(前提:你的编译器要支持typeof和type)

    学过C语言的伙伴都知道,曾经比较两个数,输出最大或最小的一个,或者是比较三个数,输出最大或者最小的那个,又或是两个数交换,又或是绝对值等等,其实这些算法在linux内核中通通都有实现,以下的代码是我从 ...

  3. 嵌入式C语言自我修养 01:Linux 内核中的GNU C语言语法扩展

    1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”.说它是C语言吧, ...

  4. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  5. C语言之linux内核实现最大公约数算法

    最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算. 两个整数的最大 ...

  6. 调皮的程序员:Linux之父雕刻在Linux内核中的故事

    本文内容由公众号“格友”原创分享. 1.引言   (不羁的大神,连竖中指都这么帅) 因为LINUX操作系统的流行,Linus 已经成为地球人都知道的名人.虽然大家可能都听过钱钟书先生的名言:“假如你吃 ...

  7. Linux 内核中的 GCC 特性

    https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...

  8. linux内核中GNU C和标准C的区别

    linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...

  9. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

随机推荐

  1. springMVC源码分析--HandlerInterceptor拦截器(一)

    对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器,HandlerInterceptor接口给我们提供了3个方法: (1)preHandle: 在执行controll ...

  2. Android Studio基本配置

    主题设置 File→Settings- 添加第三方主题 网址:http://www.ideacolorthemes.org/home/ File→Import Settings- 设置控制台字体大小 ...

  3. iOS中监控软键盘显示或隐藏的可靠方法

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 如果你试图在软键盘的显示或隐藏时去改变的UI界面结构,仅有的方 ...

  4. Calling LoadLibraryEx on ISAPI filter failed

    今天在访问IIS下的站点时莫名奇妙的遇到这个问题Calling LoadLibraryEx on ISAPI filter"C://..."  failed,前面引号中的" ...

  5. C语言一个双向链表的实现

    首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下: #ifndef DList_H #define DList_H typedef int Item; typedef struct ...

  6. 解决android 大图OOM的两种方法

    最近做程序中,需要用到一张大图.这张图片是2880*2180大小的,在我开发所用的华为3C手机上显示没有问题,但是给米3装的时候,一打开马上报OOM错误.给nexus5装,则是图片无法出来,DDMS中 ...

  7. UNIX网络编程——经常使用的套接字选项

    1.设置/获取套接字选项 int setsockopt(int socket, int level, int option_name, const void *option_value, sockle ...

  8. Android的资源类型和存储方式简介-android学习之旅(五十二)

    android资源的类型 android资源的存储方式

  9. 钩子不仅仅是windows给你留的后门

    说起钩子(Hook)熟悉windows开发的人应该比较熟悉,例如鼠标钩子.键盘钩子等.用简单的语言描述就是在正常处理流程中安置某个钩子,当执行到安置钩子的地方就将进入指定的钩子函数进行处理,待处理完再 ...

  10. React Native之Navigator

    移动应用很少只包含一个页面.从你添加第二个页面开始,就得考虑如何管理多个页面间的跳转了. 导航器正是为此而生.它可以管理多个页面间的跳转,也包含了一些常见的过渡动画,包括水平翻页.垂直弹出等等. Na ...