宏定義可以包含兩個運算符:#和##。
#運算符將一個宏的參數轉換為字符串字面量。它僅允許出現在帶參數的宏的替換列表中。#運算符有大量的用途,這裡只來討論其中的一種。
假設我們決定在調試過程中使用PRINT_INT宏作為一個便捷的方法,來輸出一個整型變量或表達式的值。#運算符可以使PRINT_INT為每個輸出的值添加標簽。下面是改進後的PRINT_INT:
#define PRINT_INT(x) printf(#x " = %d\n", x)
x之前的#運算符通知預處理器根據PRINT_INT的參數創建一個字符串字面量。因此,調用
PRINT_INT(i/j);
會變為
printf("i/j" " = %d\n", i/j);
在C語言中相鄰的字符串字面量會被合並,因此上邊的語句等價於:
printf("i/j = %d\n", i/j);
##運算符可以將兩個記號例如標識符)“粘”在一起,成為一個記號。如果其中一個操作數是宏參數,“粘合”會在當形式參數被相應的實際參數替換後發生。考慮下面的宏:
#define MK_ID(n) i##n
當MK_ID被調用時比如MK_ID(1)),預處理器首先使用自變量這個例子中是1)替換參數n。接著,預處理器將i和1連接成為一個記號i1)。下面的聲明使用MK_ID創建了3個標識符:
int MK_ID(1), MK_ID(2), MK_ID(3);
預處理後聲明變為:
int i1, i2, i3;
##運算符不屬於預處理器經常使用的特性。實際上,想找到一些使用它的情況是比較困難的。為了找到一個有實際意義的##的應用,我們來重新思考前面提到過的MAX宏。如我們所見,當MAX的參數有副作用時會無法正常工作。一種解決方法是用MAX宏來寫一個max函數。遺憾的是,往往一個max函數是不夠的。我們可能需要一個實際參數是int值的max函數,還需要參數為float值的max函數,等等。除了實際參數的類型和返回值的類型之外,這些函數都一樣。因此,這樣定義每一個函數似乎是個很蠢的做法。
解決的辦法是定義一個宏,並使它展開後成為max函數的定義。宏會有唯一的參數type,它表示形式參數和返回值的類型。這裡還有個問題,如果我們是用宏來創建多個max函數,程序將無法編譯。C語言不允許在同一文件中出現兩個同名的函數。)為了解決這個問題,我們是用##運算符為每個版本的max函數構造不同的名字。下面是宏的顯示形式:
#define GENERIC_MAX (type) \
type type##_max(type x, type y) \
{ \
return x > y ? x : y; \
}
請注意宏的定義中是如何將type和_max相連來形成新函數名的。
現在,假如我們需要一個針對float值的max函數。下面是如何使用GENERIC_MAX宏來定義函數:
GENERIC_MAX(float)
預處理器會將這行展開為下面的代碼:
float float_max(float x, float y) { return x > y ? x : y; }
本文出自 “孫轲的技術博客” 博客,請務必保留此出處http://sunke.blog.51cto.com/4812218/1290137