先說一下本文中會提到的內容:##,__va_args__, __file__, __line__ , __function__等
巨集變數:
先舉乙個例子,會用到上面這些巨集:
[cpp]view plain
copy
#define myprintf(...) printk("[lch]:file:%s, line:%d, function:%s," \
__va_args__, __file__, __line__ ,__function__);
此處的 #define 的作用是將 myprintf( )換成後面那一大串的內容,而括號內 ... 的內容原樣抄寫在 __va_args__ 的位置。最終輸出如下:
[lch]:file:arch/arm/mach-omap2/board-omap3wscec-camera.c, line:163, function:beagle_cam_init,camera init!
解析:
1)__va_args__:總體來說就是將左邊巨集中 ... 的內容原樣抄寫在右邊 __va_args__ 所在的位置。它是乙個可變引數的巨集,是新的c99規範中新增的,目前似乎只有gcc支援(vc從vc2005開始支援)。要注意的是,printf 的輸出格式是括號內左邊是字串,右邊是變數,而且右變數與左輸出格式是一一對應的。所以在上面那個例子中, __va_args__只能是一些不含任何變數的字串常量。因為上面的例子中若__va_args__含有變數,整個printf的輸出與變數便不能一一對應,輸出會出錯。
如果僅僅是替換函式名,可用如下方式,此時對__va_args__無任何特殊要求:#define myprintf(...) printk( __va_args__),在除錯程式時可以這樣用:
[cpp]view plain
copy
#ifndef log_ndebug_function
#define logfunc(...) ((void)0)
#else
#define logfunc(...) (printk(__va_args__))
#endif
2) __file__ :巨集在預編譯時會替換成當前的源檔名
3) __line__:巨集在預編譯時會替換成當前的行號
4) __function__:巨集在預編譯時會替換成當前的函式名稱
5)類似的巨集還有 __time__,__stdc__, __timestamp__等,就完全當乙個變數來使用即可。
巨集連線符##:
舉個例子:巨集定義為#define xname(n) x##n,**為:xname(4),則在預編譯時,巨集發現xname(4)與xname(n)匹配,則令 n 為 4,然後將右邊的n的內容也變為4,然後將整個xname(4)替換為 x##n,亦即 x4,故 最終結果為 xname(4) 變為 x4.
**如下:
[cpp]view plain
copy
#include
#define xname(n) x ## n
#define print_xn(n) printf("x" #n " = %d/n", x ## n);
intmain(
void
)
輸出為:x1 = 14, x2 = 20
ps:編譯過程:
1,掃瞄解析檔案
2,預處理(巨集在此時處理,該替換的文字會被替換)
3,對處理過的源**進行彙編,輸出組合語言的**(c語言的控制流程被處理)
4,編譯為二進位制目標檔案
5,與程式庫進行鏈結,輸出最終的程式檔案
(巨集 和 c語言在不同的階段處理執行)
簡單介紹以下幾個巨集:
1) __va_args__ 是乙個可變引數的巨集,這個可變引數的巨集是新的c99規範中新增的,目前似乎只有gcc支援(vc6.0的編譯器不支援)。巨集前面加上##的作用在於,當可變引數的個數為0時,這裡的##起到把前面多餘的","去掉,否則會編譯出錯。
2) __file__ 巨集在預編譯時會替換成當前的源檔名
3) __line__巨集在預編譯時會替換成當前的行號
4) __function__巨集在預編譯時會替換成當前的函式名稱
1.重新定義系統的nslog,__optimize__ 是release 缺省會加的巨集
#ifndef __optimize__
#define nslog(...) nslog(__va_args__)
#else
#define nslog(...){}
#endif
2.直接自己寫#define,當release版本的時候把#define 注釋掉即可
#define ios_debug
#ifdef ios_debug
#define nslog(...) nslog(__va_args__)
#endif
3.
#ifdef debug
# define dlog(format, ...) nslog((@"[檔名:%s]" "[函式名:%s]" "[行號:%d]" format), __file__, __function__, __line__, ##__va_args__);
#else
# define dlog(...);
#endif
這種方式需要修改專案的配置,使得在debug編譯的時候,編譯dlog的巨集,產生詳細的日誌資訊,而release的時候,不產生任何控制台輸出
相比而言,還是第一種比較方便
iOS 巨集的使用
由於平時在開發過程中,經常有遇到使用巨集 常量的時候。但是一直對這兩者的使用有些疑惑。尤其是對const的使用更加模糊,只知道該修飾符有很多種用法,位置不同含義不同。所以特意查詢了一下,為了以後方便自己查閱特此記錄一下。巨集就相當於是文字替換操作,是編譯期語法,並不會占用到記憶體,因為實質上它根本就...
ios 靈活使用巨集
繼承於c語言和c 中的巨集定義,oc中也可以方便有效的支援巨集定義使用,簡單的巨集定義誰都知道,比如定義乙個int型常量,string型別的字串都可以。如果複雜一些呢,比如用巨集定義實現單例,實現類的歸檔操作,其實都是可以的。就以類的歸檔操作為例,說明一下 現有巨集定義 sscodingimplem...
C C 巨集的高階使用1 0
單個 引例1.include define p x printf s d n x,x int main 引例2 include define printfun x printf s x void gogogo 在函式裡面列印函式名 int main 2.兩個 引例1 include h define...