你用過宏##粘貼函數(shù),然后用函數(shù)指針查找執(zhí)行嗎?
轉(zhuǎn)載授權(quán)以及圍觀:歡迎添加微信公眾號:羽林君
一、#define的常規(guī)操作????#define預(yù)處理器指令和其他預(yù)處理器指令一樣, 以#號作為一行的開
始。ANSI和后來的標(biāo)準(zhǔn)都允許#號前面有空格或制表符, 而且還允許在#和
指令的其余部分之間有空格。但是舊版本的C要求指令從一行最左邊開始,
而且#和指令其余部分之間不能有空格。指令可以出現(xiàn)在源文件的任何地
方, 其定義從指令出現(xiàn)的地方到該文件末尾有效。我們大量使用#define指令來定義明示常量(manifest constant) (也叫做符號常量) 。
????預(yù)處理器指令從#開始運(yùn)行, 到后面的第1個換行符為止。也就是說, 指
令的長度僅限于一行。然而,?在預(yù)處理開始前, 編譯器會把多行物理行處理為一行邏輯行。
一般我們會用#define 來進(jìn)行明示常量,或者做一個簡單的宏替換函數(shù)
#define RX_BUF_SIZE 30
#define MBEDTLS_DES_C /*數(shù)據(jù)加密*/
#define ExitIsr Encoder_Isr
void Encoder_Isr(void)
{
g.dir_count = (g.dir == 1)? 1 : -1;
}
????每行#define(邏輯行) 都由3部分組成。第1部分是#define指令本身。第2部分是選定的縮寫, 也稱為宏。有些宏代表值(如本例) , 這些宏被稱為
類對象宏?。C 語言還有類函數(shù)宏?, 稍后討論。宏的名稱中不允許有空格, 而且必須遵循C變量的命名規(guī)則:只能使用字符、 數(shù)字和下劃線(_) 字符, 而且首字符不能是數(shù)字。第3部分(指令行的其余部分) 稱為替換列表或替換體?。
????????一旦預(yù)處理器在程序中找到宏的實例后, 就會用替換體代替該宏。從宏變成最終替換文本的過程稱為宏展開。注意, 可以在#define行使用標(biāo)準(zhǔn)C注釋。如前所述, 每條注釋都會被一個空格代替。
此外我們還會比較多的使用變宏參
通過把宏參數(shù)列表中最后的參數(shù)寫成省略號(即, 3個點(diǎn)...) 來實現(xiàn)這
一功能。這樣, 預(yù)定義宏_ _VA_ARGS_ _可用在替換部分中, 表明省略號代表什么。?
#define PR(...) printf(_ _VA_ARGS_ _)
假設(shè)稍后調(diào)用該宏:PR("Howdy");
PR("weight = %d, shipping = $%.2f\n", wt, sp);
對于第1次調(diào)用, _ _VA_ARGS_ _展開為1個參數(shù):"Howdy"。對于第2次調(diào)用, _ _VA_ARGS_ _展開為3個參數(shù):"weight = %d,
shipping = $%.2f\n"、 wt、 sp。
因此, 展開后的代碼是:
printf("Howdy");
printf("weight = %d, shipping = $%.2f\n", wt, sp);
二、#define配合##使用????很多人應(yīng)該都知道"##"的用法,它被稱為預(yù)處理的粘合劑,與#運(yùn)算符類似,##運(yùn)算符可用于類函數(shù)宏的替換部分。而且,##還可以用于對象宏的替換部分。##運(yùn)算符可以把兩個記號組合成一個記號。
#define?def_u32_array(__name,?__size)?????uint32_t?array_##__name[__size];
實際中,我們可以這樣使用:def_u32_array(sample_buffer, 64)
宏展開的效果是:uint32_t?array_sample_buffer[64];
同樣類比于初始化一個數(shù)組,我們也可以粘貼形成一個函數(shù)下面就是在Linux內(nèi)核里面的源代碼:其中這個__pcpu_size_call_return宏,通過##粘貼選擇要使用的raw_cpu_read_x 函數(shù)。
#define __pcpu_size_call_return(stem, variable) \
({ \
typeof(variable) pscr_ret__; \
__verify_pcpu_ptr(