c語言巨集定義 define

2021-09-22 13:53:31 字數 3737 閱讀 4406

數值巨集常量

#define 巨集定義可以定義在**的任何地方,從本行巨集定義開始到後面**都認識這個巨集;可以把任何東西定義成巨集。因為編譯器在預編譯的時候用真身替換替身,然而在**裡面卻又常用替身來幫忙。巨集定義是個演技高超的替身演員,但也會經常耍大牌的,我們慎用它。

#define pi 3.141592654

在**中你盡可以使用pi來代替3.141592654,若你要把pi精度再提高一些,你需要乙個乙個的去修改這串數,你能保證不漏不出錯?若使用pi的巨集定義的話,我們只需要修改一次(十分高效)。

這種情況還不是最糟糕的,下面再看乙個例子:

#define error_poweroff  -1

如果你在**裡不用error_poweroff這個巨集而用-1,尤其在函式返回錯誤**的時候(往往乙個開發乙個系統需要定義很多錯誤**)。肯怕上帝都無法知道-1表示的是什麼意思吧。這個-1,我們一般稱為「魔鬼數」,上帝遇到它也會發狂的。所以,從**可讀性的角度進行考慮,**裡一定不要出現「魔鬼數」。

但是我們利用define來定義數值型別的資料,一般只是用來定義常量 ,如果要定義一些變數,則可以使用c語言中const關鍵字。const 修飾的資料是有型別的,而define 巨集定義的資料沒有型別。為了安全,我建議你在定義一些巨集常數時用const代替,編譯器會給const 修飾的唯讀變數做型別校驗,減少錯誤的可能。

const修飾的不是常量而是readonly的變數,const 修飾的唯讀變數不能用來定義陣列的維數,也不能放在case關鍵字後面。

字串巨集常量

除了定義巨集常數之外,經常還用來定義字串,尤其是路徑:

a) #define eng_path_1 e:\glish\lisen_to_tis\listen_to_this_3

b) #define eng_path_2 「e:\glish\liten_to_tis\listen_to_this_3」

到底哪乙個正確呢?如果路徑太長,一行寫下來比較彆扭,用反斜槓接續符 '\' :

c)  #define eng_path_3 e:\glish\lisen_to_tis\listen\_to_this_3  

這裡用了4 個反斜槓,哪個是接續符?反斜槓作為接續符時,在本行其後面不能再有任何字元,空格都不行。所以,只有最後乙個反斜槓才是接續符。至於a)和b),那要看你怎麼用了,既然define 巨集只是簡單的替換,那給eng_path_1 加上雙引號不就成了:「eng_path_1」。

注意:有的系統裡規定路徑的要用雙反斜槓「\\」,比如(這是正確的版本):

#define eng_path_4 e:\\glish\\lisen_to_tis\\listen_to_this_3 

注釋符號

#define bs //

#define bm /*

#define em */

1) bs my single-line comment

2) bm my multi-line comment em

1)、2)都是錯誤的,因為注釋先於預處理指令被處理,當這兩行被展開成//…或/*…*/時,注釋已處理完畢,此時再出現//…或/*…*/自然錯誤。因此,試圖用巨集開始或結束一段注釋不可行。

巨集定義表示式

定義一年有多少秒:

#define second_one_year 60*60*24*365

在16位系統下把這個數賦給整型變數的時候可能會溢位?一年有多少秒不可能是負數。修改一下:

#define second_one_year (60*60*24*365)ul

這裡的括號是否有必要?接著看,定義乙個巨集函式,求x 的平方:

#define sor (x)  x * x

試試:假設x 的值為100,sor (x)被替換後變成100*100,沒有問題。

再試試:假設x 的值是個表示式100+1,sor (x)被替換後變成100+1*100+1。問題來了,這並不是我想要得到的。怎麼辦?括號括起來不就完了?

#define sor (x) ((x)*(x))

最好在最外層也加上括號,看例子,求兩個數的和:

#define add (x) (x)+(x)

如果x 是個表示式50*3,**又寫成這樣:add(x)* add(x)。替換後:(50*3)+(50*3)*(50*3)+(50*3)。出錯,所以最外層的括號最好別省。define 是個演技高超的替身演員,但也經常耍大牌。要搞定它其實很簡單,加上括號。

注意這一點:巨集函式被呼叫時是以實參代換形參。而不是「值傳送」。 

巨集定義中的空格

#define sum (x) (x)+(x)

這還是定義的巨集函式sum(x)嗎?顯然不是。編譯器認為這是定義了乙個巨集:sum,代表的是(x) (x)+(x)。

為什麼會這樣呢?問題還在於sum 後面的這個空格。所以在定義巨集的時候一定要注意什麼時候該用空格,什麼時候不該用空格。這個空格僅僅在定義的時候有效,在使用這個巨集函式的時候,空格會被編譯器忽略掉。也就是說,上一節定義好的巨集函式sum(x)在使用的時候在sum 和(x)之間留有空格是沒問題的。比如:sum(3)和sum (3)的意思是一樣的。 

#undef

#undef 是用來撤銷巨集定義的,用法如下:

#define pi 3.141592654

......      // code

#undef pi  

//下面的**就不能用pi 了,它已經被撤銷了巨集定義。

寫好c語言,漂亮的巨集定義很重要,使用巨集定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟體中常用得巨集定義:

1,防止乙個標頭檔案被重複包含

#ifndef comdef_h 

#define comdef_h

//標頭檔案內容

#endif 

得到指定位址上的乙個位元組或字

#define mem_b( x ) (*((byte*) (x)))

#define mem_w( x ) (*( (word*) (x)))  

求最大值和最小值

#define max(x, y) (((x) > (y)) ? (x) : (y))

#define min(x, y) (((x) < (y)) ? (x) : (y))

返回陣列元素的個數

#define arr_size(a) (sizeof((a)) / sizeof( (a[0])))

ansi標準說明了五個預定義的巨集名。它們是:

_ line _

_ file _

_ date _

_ time _

_ stdc _

當定義了_debug,輸出資料資訊和所在檔案所在行

#ifdef _debug

#define debugmsg(msg,date) printf(msg); printf(「%d%d%d」, date, _line_, _file_)

#else

#define debugmsg(msg,date)

#endif

C 巨集定義 define

可以用 define命令將乙個指定的識別符號 即巨集名 來代表乙個字串。定義巨集的作用一般是用乙個短的名字代表乙個長的字串。它的一般形式為 define 識別符號 字串 這就是已經介紹過的定義符號常量。如 define pi 3.1415926 還可以用 define命令定義帶引數的巨集定義。其定義...

C語言 define拼接巨集定義實現

使用場合 拼接兩個巨集,乙個是傳入的巨集。但是傳入的巨集不會被替換,反而原封不動的接了上去,這就尷尬了。經過各種嘗試,居然成了,特此記錄分享一下,方便大家學習。char a param 0 char b param 0 新增巨集定義 define define x x param 一次定義 defi...

C語言 巨集定義 define的用法

這種用法是最簡單最常見的一種方式,如下 define pai 3.14注意 它的功能是在程式中若出現了pai,就把它替換為3.14,示例程式如下 include define pai 3.14 不帶參巨集定義 intmain 使用方法如下 define add a,b a b 它的功能是計算a b的...