關於宏

我在學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))

這些就是關於宏的一些知識


參考《刪繁就簡——單片機入門到精通》


天天都進步一點鄙視

相關文章
相關標籤/搜索