1. 程式人生 > >C語言巨集定義和巨集定義函式

C語言巨集定義和巨集定義函式

轉自:http://blog.sina.com.cn/s/blog_861912cd0100tc94.html

要寫好C語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。

  在軟體開發過程中,經常有一些常用或者通用的功能或者程式碼段,這些功能既可以寫成函式,也可以封裝成為巨集定義。那麼究竟是用函式好,還是巨集定義好?這就要求我們對二者進行合理的取捨。

  我們來看一個例子,比較兩個數或者表示式大小,首先我們把它寫成巨集定義:

  #define MAX( a, b) ( (a) > (b) (a) : (b) )

  其次,把它用函式來實現:

  int max( int a, int b)

  {

  return (a > b a : b)

  }

  很顯然,我們不會選擇用函式來完成這個任務,原因有兩個:首先,函式呼叫會帶來額外的開銷,它需要開闢一片棧空間,記錄返回地址,將形參壓棧,從函式返回還要釋放堆疊。這種開銷不僅會降低程式碼效率,而且程式碼量也會大大增加,而使用巨集定義則在程式碼規模和速度方面都比函式更勝一籌;其次,函式的引數必須被宣告為一種特定的型別,所以它只能在型別合適的表示式上使用,我們如果要比較兩個浮點型的大小,就不得不再寫一個專門針對浮點型的比較函式。反之,上面的那個巨集定義可以用於整形、長整形、單浮點型、雙浮點型以及其他任何可以用“>”操作符比較值大小的型別,也就是說,巨集是與型別無關的。

  和使用函式相比,使用巨集的不利之處在於每次使用巨集時,一份巨集定義程式碼的拷貝都會插入到程式中。除非巨集非常短,否則使用巨集會大幅度增加程式的長度。

  還有一些任務根本無法用函式實現,但是用巨集定義卻很好實現。比如引數型別沒法作為引數傳遞給函式,但是可以把引數型別傳遞給帶參的巨集。

  看下面的例子:

  #define MALLOC(n, type) \

  ( (type *) malloc((n)* sizeof(type)))

  利用這個巨集,我們就可以為任何型別分配一段我們指定的空間大小,並返回指向這段空間的指標。我們可以觀察一下這個巨集確切的工作過程:

  int *ptr;

  ptr = MALLOC ( 5, int );

  將這巨集展開以後的結果:

  ptr = (int *) malloc ( (5) * sizeof(int) );

  這個例子是巨集定義的經典應用之一,完成了函式不能完成的功能,但是巨集定義也不能濫用,通常,如果相同的程式碼需要出現在程式的幾個地方,更好的方法是把它實現為一個函式。

  下面總結和巨集和函式的不同之處,以供大家寫程式碼時使用,這段總結摘自《C和指標》一書。

C語言巨集定義和巨集定義函式

 

 

example:

define的單行定義

#define maxi(a,b) (a>;b?a:b)
define的多行定義

define可以替代多行的程式碼,例如MFC中的巨集定義(非常的經典,雖然讓人看了噁心)

#define   MACRO(arg1,   arg2)   do   {   \
   \
stmt1;   \
stmt2;   \
   \
  while(0)  
關鍵是要在每一個換行的時候加上一個 "\ "


//巨集定義寫出swap(x,y)交換函式
#define swap(x, y)\
x = x + y;\
y = x - y;\
x = x - y;


zigbee裡多行define有如下例子

#define FillAndSendTxOptions( TRANSSEQ, ADDR, ID, LEN, TxO ) { \
afStatus_t stat;                                    \
ZDP_TxOptions = (TxO);                              \
stat = fillAndSend( (TRANSSEQ), (ADDR), (ID), (LEN) );          \
ZDP_TxOptions = AF_TX_OPTIONS_NONE;                 \
return stat;                                        \
}