要點:變數都用括號括起來,防止出錯,結尾不需要;。在實際程式設計中,不推薦把複雜的函式使用巨集,不容易除錯。多行用\
要寫好c語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高**的可移植性和可讀性等。
在軟體開發過程中,經常有一些常用或者通用的功能或者**段,這些功能既可以寫成函式,也可以封裝成為巨集定義。那麼究竟是用函式好,還是巨集定義好?這就要求我們對二者進行合理的取捨。
我們來看乙個例子,比較兩個數或者表示式大小,首先我們把它寫成巨集定義:
#define max(a, b) ((a) > (b) ? (a):(b))
其次,把它用函式來實現:
int max(int a, int b)
很顯然,我們不會選擇用函式來完成這個任務,原因有兩個:首先,函式呼叫會帶來額外的開銷,它需要開闢一片棧空間,記錄返回位址,將形參壓棧,從函式返回還要釋放堆疊。這種開銷不僅會降低**效率,而且**量也會大大增加,而使用巨集定義則在**規模和速度方面都比函式更勝一籌;其次,函式的引數必須被宣告為一種特定的型別,所以它只能在型別合適的表示式上使用,我們如果要比較兩個浮點型的大小,就不得不再寫乙個專門針對浮點型的比較函式。反之,上面的那個巨集定義可以用於整形、長整形、單浮點型、雙浮點型以及其他任何可以用「>」操作符比較值大小的型別,也就是說,巨集是與型別無關的。
和使用函式相比,使用巨集的不利之處在於每次使用巨集時,乙份巨集定義**的拷貝都會插入到程式中。除非巨集非常短,否則使用巨集會大幅度增加程式的長度。
還有一些任務根本無法用函式實現,但是用巨集定義卻很好實現。比如引數型別沒法作為引數傳遞給函式,但是可以把引數型別傳遞給帶參的巨集。
看下面的例子:
#define malloc(n, type) \((type *) malloc((n)* sizeof(type))
利用這個巨集,我們就可以為任何型別分配一段我們指定的空間大小,並返回指向這段空間的指標。我們可以觀察一下這個巨集確切的工作過程:
int *ptr;ptr = malloc( 5, int );
將這巨集展開以後的結果:
ptr = (int *) malloc ( (5) * sizeof(int) );
這個例子是巨集定義的經典應用之一,完成了函式不能完成的功能,但是巨集定義也不能濫用,通常,如果相同的**需要出現在程式的幾個地方,更好的方法是把它實現為乙個函式。
屬性#define巨集
函式**長度
每次使用時,巨集**都被插入到程式中。除了非常小的巨集之外,程式的長度將大幅度增長。
函式**只出現於乙個地方:每次使用這個函式時,都呼叫那個地方的同乙份**
執行速度
更快存在函式呼叫、返回的額外開銷
操作符優先順序
巨集引數的求值是在所有周圍表示式的上下文環境裡,除非它們加上括號,否則鄰近操作符的優先順序可能產生不可預料的結果。
函式引數只在函式呼叫時求值一次,它的結果值傳遞給函式。表示式的求值結果更容易**。
引數求值
引數用於巨集定義時,每次都將重新求值,由於多次求值,具有***的引數可能會產生不可**的結果。
引數在函式呼叫前只求值一次,在函式中多次使用引數並不會導致多次求值過程,引數的***並不會造成任何特殊問題。
引數型別
巨集與型別無關,只要引數的操作是合法的,它可以用於任何引數型別。
函式的引數是與型別有關係的,如果引數的型別不同,就需要使用不同的函式,即使它們執行的任務是相同的。
乙個巨集定義的用法
巨集定義就是簡單的替換,之前沒見過帶符號的替換,看到這個有點懵了,記錄如下。這裡用 n,代替 fninfo n,l 用的很巧妙。define fninfo n,l n,measvalue measfntbl 以下為names.h中內容 fninfo dominmaxmidhilo,min fninf...
C語言巨集定義和巨集定義函式
c語言巨集定義和巨集定義函式 巨集定義可以幫助我們防止出錯,提高 的可移植性和可讀性等。在軟體開發過程中,經常有一些常用或者通用的功能或者 段,這些功能既可以寫成函式,也可以封裝成為巨集定義。那麼究竟是用函式好,還是巨集定義好?這就要求我們對二者進行合理的取捨。我們來看乙個例子,比較兩個數或者表示式...
乙個複雜巨集定義的解讀
我們不提倡在寫 的時候出現太多複雜的巨集定義,巨集定義雖然可以簡化 量,但是讀起來非常費勁!下面來看乙個例子 把乙個buff中的資料拷貝到乙個指定的陣列中。由於種種原因,我們用巨集定義來實現這些負責的轉化。如下 include stdafx.h include string.h typedef un...