日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

你想知道的do{...}while(0)的作用,都在这里了

發布時間:2023/10/11 综合教程 130 老码农
生活随笔 收集整理的這篇文章主要介紹了 你想知道的do{...}while(0)的作用,都在这里了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0、引言        

我們在嵌入式開發的過程中,經??梢耘龅皆谝恍┖甓x或者是代碼段中使用了do {...} while(0)的語句,從語義上理解,do {...} while(0)內的邏輯就只執行一次,并沒有循環執行,粗略看來,似乎畫蛇添足了,那么為什么還需要在只執行一次的邏輯外面加上一層do {...} while(0)語句呢?實際上,在這些邏輯中使用do {...} while(0)的作用遠大于美化你的代碼,下面就來看看實際的使用場景。


1、用于定義一個作用域,避免替換的時候出錯

我們都知道,在程序中如果一些常量參數或者代碼語句反復出現,就可以使用宏定義來替代。預處理階段,對程序中所有出現的“宏名”,預處理器都會用宏定義中的字符串替代,這稱為“宏替換”或“宏展開”。

這樣做可提高程序的通用性和易讀性,減少不一致性,一個較好的宏名可以更好的讓讀者理解常量參數的含義;同時程序易于修改,我們僅需要改變一個宏定義,就可以改變整個程序中出現的所有該常量或者語句。

但是有時可能程序代碼段中,出現多條語句重復連續的使用,這樣我們就可以嘗試使用一個復雜的宏來替換。你有可能會這樣定義:

1 #define REPLACE_FUN() funA(); funB()

  本意是在程序中當出現funA()和funB()多條語句連續使用時,使用REPLACE_FUN()來替換。

1 if(判斷條件)
2 REPLACE_FUN();

但是實際上在預處理的時候,宏展開替換后變成了:

1 if(判斷條件)
2 funA();
3 funB(); //此處funB()一定會執行,造成邏輯錯誤

可以看出,funB()不會按照判斷條件才去執行。而是變成了一條獨立的語句,而如果在宏中使用括號:

1 #define REPLACE_FUN() {funA(); funB();}

我們一般的代碼習慣都會在語句的末尾加上分號,因此也會出錯:

1 if(判斷條件)
2 REPLACE_FUN();
3 //宏展開后為:
4 if(判斷條件)
5 {
6 funA();
7 funB();
8 }; //此處替換后多一個分號;導致編譯報錯

因此,針對這種多條重復語句的連續使用,如果想用宏替換實現這個作用域的功能,就可以考慮使用do {...} while(0)語句:

 1 define REPLACE_FUN() \
2 do{ \
3 funA();\
4 funB();\
5 }while(0)\
6 //宏展開前為:
7 if(判斷條件)
8 REPLACE_FUN();
9 //宏展開后為:
10 if(判斷條件)
11 do{
12 funA();
13 funB();
14 }while(0); //根據判斷條件,正確執行了一次邏輯


2、避免goto語句的使用

goto語句也稱為無條件轉移語句,使用后可以從多重循環或者多個判斷中直接跳出。對于如下例子:

 1 void fun(int a)
2 {
3 if(1 == a)
4 {
5 ...//todo
6 goto exit;
7 }
8 if(2 == a)
9 {
10 ...//todo
11 goto exit;
12 }
13 exit:
14 ...//todo
15 printf("a is error"\n);
16 }

但是為了程序結構的清晰,還是要盡量限制goto語句的使用,我們可以使用do {...} while(0)結構配合break跳出單層的循環的方法來替代這種goto的用法。

 1 int fun(int a)
2 {
3 do{
4 if(1 == a)
5 {
6 ...//todo
7 break;
8 }
9 if(2 == a)
10 {
11 ...//todo
12 break;
13 }
14 }while(0);
15 ...//todo
16 printf("a is error"\n);
17 }

3、定義一個單獨的函數塊來實現復雜的操作

當某個函數程序功能較為復雜,在該函數的代碼段中如果不再單獨定義一個函數實現部分邏輯,可以使用do {...} while(0)作為一個代碼塊,將想要實現的邏輯放在do {...} while(0)中,同時在該在do {...} while(0)代碼塊中定義的變量,可以不用考慮和函數之前或者之后的變量名重復沖突的問題。但是為了代碼的易讀性,還是盡量聲明不同的變量名。

 1 int a;
2 char b;
3 int func()
4 {
5 int a = 3;
6 char b = 5;
7 do{
8 int a;
9 char b;
10 ......//todo
11 }while(0);
12 }


4、避免空宏的警告

有的時候,程序為了不同的平臺移植或者不同架構的限制,很多時候會先定義空宏,后續再根據實際的需要看是否定義具體內容。但是在編譯的時候,這些空宏可能會給出warning,為了避免這樣的warning,我們可以使用do{...}while(0)來定義空宏,這種情況不太常見,因為有很多編譯器已經支持空宏。

1 //空宏
2 #define EMPTY_FUN
3 //增加do{...}while(0)來定義空宏
4 #define EMPTY_FUN do{}while(0) //避免了可能的編譯warning

更多技術內容和書籍資料獲取,入群技術交流敬請關注“明解嵌入式”

?

總結

以上是生活随笔為你收集整理的你想知道的do{...}while(0)的作用,都在这里了的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。