1. 程式人生 > >巨集定義#define括號使用的深入認識

巨集定義#define括號使用的深入認識

巨集定義:注意x,y值都有一個括號,和特定的符號時 需要加上括號!
// SWAP(x, y)               交換x,y的值  
#define SWAP(x, y) \  
    (y) = (x) + (y); \  
    (x) = (y) - (x); \  
    (y) = (y) - (x);  

求最大值和最小值
   #define  MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
   #define  MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

寫一個“標準”巨集MIN,這個巨集輸入兩個引數並返回較小的一個。另外,當你寫下面的程式碼時會發生什麼事?
least = MIN(*p++, b);
  解答:
#define MIN(A,B)   ((A) <= (B) ? (A) : (B))  注意外面還有一層括號!!
  MIN(*p++, b)會產生巨集的副作用
  剖析:
  這個面試題主要考查面試者對巨集定義的使用,巨集定義可以實現類似於函式的功能,但是它終歸不是函式,而巨集定義中括弧中的“引數”也不是真的引數,在巨集展開的時候對“引數”進行的是

一對一的替換。
  程式設計師對巨集定義的使用要非常小心,特別要注意兩個問題:
  (1)謹慎地將巨集定義中的“引數”和整個巨集用用括弧括起來。所以,嚴格地講,下述解答:
#define MIN(A,B) (A) <= (B) ? (A) : (B)
#define MIN(A,B) (A <= B ? A : B )
  都應判0分;
  (2)防止巨集的副作用。

巨集定義#define MIN(A,B) ((A) <= (B) ? (A) : (B))對MIN(*p++, b)的作用結果是:

((*p++) <= (b) ? (*p++) : (b)) 

這個表示式會產生副作用,指標p會作兩次++自增操作。

除此之外,另一個應該判0分的解答是:

#define MIN(A,B) ((A) <= (B) ? (A) : (B));
這個解答在巨集定義的後面加“;”,顯示編寫者對巨集的概念模糊不清。

將一個字母轉換為大寫
#define  UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )

返回陣列元素的個數 

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

對於IO空間對映在儲存空間的結構,輸入輸出處理
  #define inp(port)         (*((volatile byte *) (port)))

  #define inpw(port)        (*((volatile word *) (port)))
  #define inpdw(port)       (*((volatile dword *)(port)))

  #define outp(port, val)   (*((volatile byte *) (port)) = ((byte) (val)))
  #define outpw(port, val)  (*((volatile word *) (port)) = ((word) (val)))
  #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))

得到一個字的高位和低位位元組
#define  WORD_LO(xxx)  ((byte) ((word)(xxx) & 255))
#define  WORD_HI(xxx)  ((byte) ((word)(xxx) >> 8))

在巨集之中用do{}while(0)語句包含多語句防止錯誤。

巨集中"#"和"##"的用法 我們使用#把巨集引數變為一個字串,用##把兩個巨集引數貼合在一起.