1
#error 與#warning
談到預編譯大家常用的有#if、#else、#ifdef、#ifndef、#endif等等條件編譯選項。
然而在我們閱讀一些大型的代碼或者庫的時候,一般都會看到有#error和#warning,可能有些小伙伴一掃而過并沒有了解清楚這些預編譯指令到底該怎么用,寫了很久的代碼估計也重來沒有敲過他們。
#error / #warning
形式 :#error / #warningmessage
作用 :生成一個編譯錯誤事件并停止編譯/發出警告信息
注意 :message可以不需要雙引號。
參考demo:
#include #include //#defineconfigUART_N5 #ifndefconfigUART_N #errorconfigUART_Nmustdefine //#error"configUARTmustdefine" //#warning"configUARTmustdefine" #endif #ifconfigUART_N>4 #errorconfigUART_Nmustnotbelessthan4 //#error"configUART_Nmustnotbelessthan4" //#warning"configUART_Nmustnotbelessthan4" #endif /*************************************** *Fuction:進行預編譯測試 *Author:(最后一個bug) **************************************/ intmain(intargc,char*argv[]){ printf("公眾號;最后一個bug "); return0; }
輸出結果:
編譯失敗,無法生成可執行文件
上面是放開宏,且使用warning的情況,無其他錯誤的情況下可以生成可執行文件。
解釋一下:
通過上面的測試代碼可以了解到,通過配合條件預編譯#if等,#error和#warning能夠在編譯過程中分別以錯誤和告警的形式提醒開發人員注意相關代碼設計問題,從而保證代碼正確性。
這樣對于發布一些龐大的庫代碼時,為了讓開發人員正確的使用庫,這些提示會幫助他更好的移植代碼。
那么經常有很多小伙伴編譯出來的代碼有一大堆warning,總是覺得warning關系不大,然而warning也是分不同類型的,對于一些未使用的變量倒關系不大,其他情況還是要認真對待,最好是做到"0 Error,0 warning".
2
#undef
#undef標識符用于把前面的宏定義名取消,別看這宏用得不多,作用可大著呢,下面我簡單舉幾個例子:
1
局部宏定義
一旦定義了宏,那么該文件中往下所有的代碼都可以使用該宏,即使是函數內部,這樣導致宏比較混亂,如下面代碼:
參考demo:
#include #include #defineconfigRatio10 /*************************************** *Fuction:獲得傳感器電壓值 *Author:(最后一個bug) **************************************/ intGetSensorVolt(void) { #defineconfigRatio1 intret=0; ret=configRatio*1024;//比例因子*AD值 returnret; //#undefconfigRatio } /*************************************** *Fuction:獲得傳感器電壓值 *Author:(最后一個bug) **************************************/ intGetSensorCurr(void) { #defineconfigRatio2 intret=0; ret=configRatio*1024;//比例因子*AD值 returnret; //#undefconfigRatio } /*************************************** *Fuction:進行預編譯測試 *Author:(最后一個bug) **************************************/ intmain(intargc,char*argv[]){ printf("configRatio=%d ",configRatio);//報宏未定義 printf("GetSensorVolt=%d ",GetSensorVolt()); printf("GetSensorCurr=%d ",GetSensorCurr()); printf("公眾號;最后一個bug "); return0; }
輸出結果:
解釋一下:
假如我們沒有注意到函數內部的同名宏定義,當然告警也沒管,那么在main函數中使用同名宏定義就可能不是我們期待的最上面的宏定義,造成程序bug。
所以我們可以使用#undef來限制每個宏的作用域,如果每個函數內部都使用了#undef,那么main函數中再使用會報宏沒有定義,這樣便可以找到問題,當然也可以通過警告了解到。
2
選擇接口
通過宏來切換不同的接口供程序使用:
參考demo:
#include #include #include #defineDEV_SPI #include"Drive.h" #undefDEV_SPI /*************************************** *Fuction:進行預編譯測試 *Author:(最后一個bug) **************************************/ intmain(intargc,char*argv[]){ char*strbug="thelastbug"; SendData(strbug); ProcessData(strbug); printf("公眾號;最后一個bug "); return0; }
#include #ifdefDEV_UART #defineSendData(s)printf("UARTSend:%s ",s) #defineProcessData(s)printf("UARTProcess:%s ",s) #endif #ifdefDEV_CAN #defineSendData(s)printf("CANSend:%s ",s) #defineProcessData(s)printf("CANProcess:%s ",s) #endif #ifdefDEV_SPI #defineSendData(s)printf("SpiSend:%s ",s) #defineProcessData(s)printf("SpiProcess:%s ",s) #endif
輸出結果:
3
自定義接口
當多個人維護一套代碼的時候,有些同事喜歡調用庫函數接口,而有些同事喜歡調用自定義接口,為了方便統一使用自定義接口或者庫接口,我們會進行如下操作:
參考demo:
#include #include #include #include"Drive.h" //#undefprintf /*************************************** *Fuction:進行預編譯測試 *Author:(最后一個bug) **************************************/ intmain(intargc,char*argv[]){ char*strbug="thelastbug"; printf("公眾號;最后一個bug "); return0; }
#ifndef__DRIVE_H__ #define__DRIVE_H__ #defineprintfprintf("pleaseuseKprintf! "); externvoidKprintf(char*str); #endif
輸出結果:
這樣下面的代碼你就只能夠使用Kprintf來進行輸出打印,而當我們放開注釋掉的宏,這樣就又可以使用printf了,還是比較方便的。
責任編輯:lq
評論