C++中的巨集定義及#和##的作用
阿新 • • 發佈:2019-02-17
#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)));
注意:巨集定義中的#的意思:巨集定義中#是“字串化”的意思,是把跟在後面的引數轉換成一個字串,例如#a等同於“a”,#abc等同於“abc”。巨集定義中的##是一個連線符號,用於把引數連在一起。例如,a##b##c等同於abc
計算方法:一、如果巨集定義是帶#的,如(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""
1. ##操作符
##操作符它的作用是在替代表中將其前後的引數連線成為一個預處理符號,它不能出現於巨集替代表的開端和末尾。
例:
#define concat(s,t) s##t
#define AAA ABC
concat(A, AA)
將被替換成
ABC
2. 重新掃描和替換
在替換列表中的所有引數替換過之後,前處理器將對結果token序列重新掃描以便對其中的巨集再次替換。
當正在替換的巨集在其替換列表中發現自身時,就不再對其進行替換。今兒,在任何正在巢狀替換的巨集的替換過程中遇到正被替換的巨集就對其不再進行替換(防止遞迴)。
例:
#define ROOT AAA CCC
#define AAA ROOT
ROOT
將被替換成
ROOT CCC