1. 程式人生 > >C巨集定義中##連線符與#符的含義

C巨集定義中##連線符與#符的含義

文章目錄

參考

http://lib.csdn.net/article/c/27630

note

不帶引數的巨集

巨集定義又稱為巨集代換、巨集替換,簡稱“巨集”。
格式:

#define 識別符號 字串

其中的識別符號就是所謂的符號常量,也稱為“巨集名”。

預處理(預編譯)工作也叫做巨集展開:將巨集名替換為字串

掌握"巨集"概念的關鍵是“換”。一切以換為前提、做任何事情之前先要換,準確理解之前就要“換”

即在對相關命令或語句的含義和功能作具體分析之前就要換:
例:

#define Pi 3.1415926

把程式中出現的Pi全部換成3.1415926

附加說明:

(1)巨集名一般用大寫

(2)使用巨集可提高程式的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:陣列大小常用巨集定義

(3)預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查。

(4)巨集定義末尾不加分號;

(5)巨集定義寫在函式的花括號外邊,作用域為其後的程式,通常在檔案的最開頭。

(6)可以用#undef命令終止巨集定義的作用域

(7)巨集定義允許巢狀

(8)字串( " " )中永遠不包含巨集

(9)巨集定義不分配記憶體,變數定義分配記憶體。

(10)巨集定義不存在型別問題,它的引數也是無型別的。

帶引數的巨集

除了一般的字串替換,還要做引數代換

格式:

#define巨集名(引數表) 字串
例如:#define S(a,b) a*b

area=S(3,2);第一步被換為area=a*b; ,第二步被換為area=3*2;

類似於函式呼叫,有一個啞實結合的過程:

(1)實參如果是表示式容易出問題

#define S(r) r*r

area=S(a+b);

第一步換為area=r*r

第二步被換為area=a+b*a+b;

正確的巨集定義是

#define S(r) ((r)*(r))

(2)巨集名和引數的括號間不能有空格

(3)巨集替換隻作替換,不做計算,不做表示式求解

(4)函式呼叫在編譯後程序執行時進行,並且分配記憶體。巨集替換在編譯前進行,不分配記憶體

(5)巨集的啞實結合不存在型別,也沒有型別轉換。

(6)巨集展開使源程式變長,函式呼叫不會

(7)巨集展開不佔執行時間,只佔編譯時間,函式呼叫佔執行時間(分配記憶體、保留現場、值傳遞、返回值)

應題重點

有參巨集定義中#的用法

#define STR(str) #str

#用於把巨集定義中的引數兩端加上字串的""

比如,這裡STR(my#name)會被替換成"my#name"

一般由任意字元都可以做形參,但以下情況會出錯:

STR())這樣,編譯器不會把“)”當成STR()的引數。

STR(,)同上,編譯器不會把“,”當成STR的引數。

STR(A,B)如果實參過多,則編譯器會把多餘的引數捨去。(VC++2008為例)

STR((A,B))會被解讀為實參為:(A,B),而不是被解讀為兩個實參,第一個是(A第二個是B)。

有參巨集定義中##的用法

它為巨集的擴充套件提供了一種連線實際變元的手段,如果替換文字中的引數被##相連,那麼引數就被實際變元替換,##前後的空白被刪除,並對替換的結果進行掃描。

#define WIDE(str) L##str

則會將形參str的前面加上L

比如:WIDE(“abc”)就會被替換成L"abc"

其中的變化是: L##str L"abc"


注: 幹嘛加引號迷惑自己呢? 這樣來講吧:

define LINK(str) pre##str##after

eg: LINK(abc)

so we have : preabcafter


騷操作:

如果有#define FUN(a,b) vo##a##b()
那麼FUN(id ma,in)會被替換成void main()

實際的例子:

#define DFD_VERBOS(fmt, args...) do {                     \
    if (DFD_DEBUG_CHECK(DFD_DBG_VBOSE)) {               \
        printf("[%s-%s]:<File:%s, Func:%s, Line:%d>\n" fmt, "DFD", "vbose", \
            __FILE__, __FUNCTION__, __LINE__, ##args);  \
    }                                                   \
} while (0)