1. 程式人生 > >C語言在linux內核中do while(0)妙用之法

C語言在linux內核中do while(0)妙用之法

pos turn jsb world div fprintf cpp efault code

為什麽說do while(0) 妙?由於它的確就是妙,並且在linux內核中實現是相當的妙,我們來看看內核中的相關代碼:

#define db_error(fmt, ...)     do { 							 fprintf(stderr, "(error): ");  		 fprintf(stderr, fmt, ##__VA_ARGS__);         } while (0)
這僅僅是個普通的調試信息的輸出。有人便會覺得。你這不是多此一舉嗎?去掉do while(0)不一樣也實現了嗎?事實上不然,我們看看樣例就清楚了,雖然非常easy:

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)妙用之法