我在學C語言的時候是知道有宏這個東西的,但當時並無把它放在心上。直到後來接觸單片機時,才漸漸發現了宏的威力。面試
關於宏,有一下幾點須要說明。數組
1.宏的書寫須要用大寫函數
這不是硬性要求,可是是一個通用的準則。這是爲了和變量,函數等聲明區分開來。算是使用宏的第一準則(我剛開始根本不知道這些)測試
2.程序中的各類定義儘可能用宏spa
好比寫單片機程序,咱們常常將跟硬件有關的定義寫成宏。好比 #define LED P3。這樣是爲了之後當換硬件平臺時,方便移植與修改,只須要將宏後面的表明項改變就是了。還有經常用到宏的地方就是一些常量。好比一個測試值的最大值只能到200,程序中咱們會常常用到這個值與之比較。那麼就能夠定義宏 #define MAX 200。這樣若是方便程序修改,同時也使代碼更加清晰了很多。調試
3.防止頭文件被包含code
開始學寫本身的頭文件的時候,我根本不知道有這些。因此,當信心滿滿的寫好本身的頭文件加到工程中編譯連接,結果出現了重複定義的錯誤。後來上網才知道是由於頭文件的重複包含致使。因而學會了用宏進行處理。處理過程很簡單,只須要在所寫頭文件中寫下以下代碼it
#ifndef _MYHEADER_H #define _MYHEADER_H //頭文件內容 #endif (_MYHEADER_H)
4.使用宏定義表達式須要使用完備的括號防止出錯編譯
當在宏定義中須要用到運算表達式時,最好給每一個參數都加上括號。注意,是每一個。下面就是一個例子:入門
#define SQUARE(x) (x*x)
依照這種宏定義的話那麼SQUARE(1+2) = 1+2*1+2 = 5 。結果就爲5,而不是咱們想要的9
因此正確的宏定義爲
#define SQUARE(x) ((x)*(x))
這樣把每一個參數都包含起來,就不會出錯了。
5.使用宏時不容許參數發生變化
#define SQUARE((x)*(x))
int a = 2;
int b;
b = SQUARE(a++); //SQUARE(a++) = (a++)*(a++),結果執行了兩次加一操做,結果爲4
正確的操做應該是:
b = SQUARE(a);
a++; //只執行一次累加結果爲3
6.使用宏定義的表達式應放在大括號中
就像這樣:
#defined INIT_VALUE(x,y)\
{\
x=0;\
y=0;\
}
"\"表示下一行繼續爲宏定義的內容
7.將經常使用數據類型從新定義,方便因爲平臺不一樣而產生的類型字節數差別,方便移植。
這個是頗有用的,因此咱們常常會看到有些單片機的模版文件中有一個配置頭文件"config.h"這裏面就包含了經常使用數據的定義。若是當平臺更換時,若是數據類型不一樣,咱們則只需修改宏就是了,很方便。
8.使用宏進行跟蹤調試
#define DEBUGMSG(msg)\
{\
#ifdef _DEBUG_\
printf(msg);\
#endif\
}
主要是爲了程序的連續調試。
下面展現了是一些實用的宏實例
//求最大值和最小值 #define MAX(x,y) (((x)>(y))? (x):(y)) #define MIN(x,y) (((x)<(y))? (x):(y)) //高低字節操做,類型爲自定義類型 #define HI_BYTE(n) (UINT8)((n>>8)&0xFF) #define LO_BYTE(n) (UINT8)(n&0xFF) #define BYTE2WORD(hi,lo) (UINT16)((hi<<8)|lo) //高低字操做,類型爲自定義類型 #define HI_WORD(n) (UINT16)((n>>16)&0x0FFFF) #define LO_WORD(n) (UINT16)(n&0x0FFFF) #define WORD2DWORD(hi,lo) (UINT32)(((UINT32)hi << 16)|lo) //讀、寫指定地址上的字節 #define MEM_BYTE(x) (*((UINT8 *)(x))) //字母大小寫轉換 #define UPCASE(c) (((c)>='a'&&(c)<='z')? ((c)-0x20):(c)) #define LOWCASE(c) (((c)>='A'&&(c)<='Z')? ((c)+0x20):(c)) //十進制和BCD轉換 #define BCD_TO_DEC(bcd) ((((UINT8)(bcd))>>4)*10 + (((UINT8)(bcd))&0x0f))) #define DEC_TO_BCD(dec) ((((((UINT8)(dec))/10)<<4)|((UINT8)(dec))%10)) //返回數組元素的個數 #define ARR_SIZE(a) (sizeof((a))/sizeof((a[0]))) //位操做 #define TEST_BIT(x,offset) (1&((x)>>offset))) #define SET_BIT(x,offset) ((x)|=(1<<offset))) #define CLR_BIT(x,offset) ((x)&=(~(1<<(offset)))) //面試常問的用宏表示一年有多少時間(留意溢出) #define MINS_OF_YEAR ((UINT32)(365*24*60)) #define SECS_OF_YEAR ((UINT32)(365*24*60*60))
參考《刪繁就簡——單片機入門到精通》
天天都進步一點