在宏定義中經常看到符號#
和##
的使用,該篇博客就結合宏定義的展開方式說明這兩種符號的具體作用。
本文參考學習該篇博客:參考來源——#和##的用法
用法說明
#define f(a,b) a##b // (1)
#define g(a) #a // (2)
#define h(a) g(a) // (3)
在上述三個宏定義中使用了符號#
和##
,使用上述宏如下代碼所示
printf("%s\n", g(f(1, 2)));
printf("%s\n", h(f(1, 2)));
輸出以下結果:
f(1, 2)
12
根據以上代碼的輸出結果,可以總結出#
和##
的用法:
符號#表示“字符串化”的意思,就是把跟在後面的參數轉換成一個字符串,例如上述代碼中g(f(1, 2))輸出的結果爲f(1, 2)
符號##是一個連接符號,用於把參數連在一起,例如a##b等同於ab
但是大家一定對於上述代碼中第二輸出感覺到很疑惑,想當然認爲輸出結果爲f(1, 2)
,這裏就需要注意以下兩點:
如果宏定義是帶#的,如(2)所示,則直接替換。g(f(1,2))--->#f(1,2)--->"f(1,2)"
如果宏定義是不帶#的,如(1)、(3)所示,基本原則爲展開參數然後替換。
步驟爲:由外層向裏層走,如果碰到的是以非#開頭的宏,則繼續往裏層走,直到最裏層,然後開始往外層展開。
如果碰到的是以#開頭的宏,則不再往裏層走,往外層展開。h(f(1,2))--->h(12)--->g(12)--->#12--->"12"
下面再舉一些例子,大家可以在每行代碼的後面看到具體的輸出結果:
char a = 'c';
cout << g(a) << endl; // "a"
cout << g(g(a)) << endl; // "g(a)"
printf("%s\n", h(f(1, 2))); // "12"
printf("%s\n", g(f(1, 2))); // "f(1,2)"
printf("%s\n", g(h(f(1, 2)))); // "h(f(1,2))"
printf("%s\n", h(g(f(1, 2)))); // ""f(1,2)""
printf("%s\n", h(h(f(1, 2)))); // ""12""