1、引言 說到預編譯,大家立刻就能想到#define、#if、#ifdef和#ifndef等熟悉的預編譯命令。其實#include,我們通常放在源文件用來包含頭文件,它也是預編譯命令。當然這不是這篇文章的重點。 這篇文章主要講解下#error預編譯命令,對於什麼是預編譯,預編譯的作用等基礎知識點不再 ...
1、引言
說到預編譯,大家立刻就能想到#define、#if、#ifdef和#ifndef等熟悉的預編譯命令。其實#include,我們通常放在源文件用來包含頭文件,它也是預編譯命令。當然這不是這篇文章的重點。
這篇文章主要講解下#error預編譯命令,對於什麼是預編譯,預編譯的作用等基礎知識點不再講解,不懂的同學請自行百度。
在MCU的開發中,我們經常需要用到Flash存儲一些參數,且通常情況下有很多參數需要存儲。
一般採用一個扇區存儲一種類型的參數(可能造成Flash空間浪費),但對於一些內部Flash容量很大的MCU,這樣做也是可行的。
示例demo如下
#define PARA_BATTERY_ADDR 0x08019000 //存儲電池參數 #define PARA_ETH_ADDR 0x0801B800 //存儲網路參數 .......... #define PARA_USER_CONFIG_ADDR 0x0801C400 //存儲用戶參數
很多開發工程師喜歡這樣做,如果參數少時還好,當有很多參數時,這將是一個噩夢。如果這些參數分散在各個文件中,閱讀這份源碼將是噁心他媽給噁心開門,噁心到家了。
當想增加一個參數存儲時,如果不很熟悉代碼,根本不知道哪個扇區是空閑的。
優化版本如下,將這這些巨集定義統一定義在flashmap.h中
#define PARA_STARADDR (0x08000+(100*1024)) //前100K用於存儲固件,參數存儲開始地址。 #define FLASH_SECTOR_SIZE (2*1024) //Flash每個扇區的大小 #define PARA_BATTERY_ADDR PARA_STARADDR //存儲電池參數 #define PARA_BATTERY_SIZE (1*FLASH_SECTOR_SIZE) //電池參數所占空間大小 #define PARA_ETH_ADDR (PARA_BATTERY_ADDR+PARA_BATTERY_SIZE) //存儲網路參數 #define PARA_ETH_SIZE (2*FLASH_SECTOR_SIZE) //網路參數所占空間大小
相信大家也看出來了,這樣管理參數地址,就顯得很合理,不會想增加一個參數時,不知道哪個扇區是空閑的,找到了一個扇區,還是擔心受怕,害怕和別的參數存儲地址衝突將其覆蓋。
當然它也有弊端,如果問你PARA_ETH_ADDR存儲地址,並不能立刻從代碼中看出,這個問題,我一般使用printf列印出來。
還有個問題,如果加了很多參數,最後一個參數地址大於Flash空間怎麼辦,或者軟體設計一段Flash空間作為參數區,不被允許超過這個地址。
在這個代碼結構中,無法從代碼中直接獲取,有不行使用printf肉眼判斷,那麼可以使用#error 解決這個問題。
2、#error
#error 是一種預編譯器指示字,用於生成一個編譯錯誤消息 。
用法:#error [message] //message為用戶自定義的錯誤提示信息,可預設。
#error 可用於提示編譯條件是否滿足。編譯過程中的任何錯誤意味著無法生成最終的可執行程式。
上面的程式優化為
#define PARA_STARADDR (0x08000+(100*1024)) //前100K用於存儲固件,參數存儲開始地址。 #define FLASH_SECTOR_SIZE (2*1024) //Flash每個扇區的大小 #define PARA_BATTERY_ADDR PARA_STARADDR //存儲電池參數 #define PARA_BATTERY_SIZE (1*FLASH_SECTOR_SIZE) //電池參數所占空間大小 #define PARA_ETH_ADDR (PARA_BATTERY_ADDR+PARA_BATTERY_SIZE) //存儲網路參數 #define PARA_ETH_SIZE (2*FLASH_SECTOR_SIZE) //網路參數所占空間大小 #define PARA_END_ADDR (PARA_ETH_ADDR+PARA_ETH_SIZE)// 參數的結束地址 #if (PARA_END_ADDR > 0x0801E000) #error Flash Map Error #endif
這樣當你的參數最後地址大於0x0801E000,編譯器機會報錯,根本編譯不過,如下圖
類似的,#warning 用於生成編譯警告消息。warning可用來提示一些非致命錯誤。
3、其他用法
限定巨集定義的數值範圍,下麵SIZE被限制在0到100內。
#define SIZE 10 #if SIZE < 0 || SIZE > 100 #error SIZE must be between 1 and 100. #endif uint8_t buffer[SIZE];
指定使用VS編譯器.
#ifndef _MSC_VER #error require visual studio compiler #endif
判斷是否定義了某個巨集,比如FreeRTOS源碼中
#ifndef configMINIMAL_STACK_SIZE #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. #endif
點擊查看:C語言進階專輯