c 中巨集備忘

2021-08-30 18:20:35 字數 1382 閱讀 2972

來自:

1.巨集不要用來定義常量,因為巨集變數是沒有型別安全的,也沒有名字空間約束,會造成名字的汙染。

2.巨集的展開是一行,所以巨集中的注釋不能使用//,只能使用/* */。巨集的**也不能gdb跟蹤,巨集中**邏輯要盡量簡單。

3.巨集的引數一般情況下使用時要用()括起來,如

#define max(a, b) a /2 > b ? a /2 : b

max(3,4)使用沒有問題,但max(3+4, 4)卻有問題,因為巨集的引數僅為符號替換。

應用定義為#define max(a, b) (a) / 2 > (b) ? (a) /2 : (b)

4.巨集的連線符分為#與##

#表示乙個符號直接轉換為字串,如

#define cat(x) "first "#x " third"

const char * pszstr = cat(second); str的內容就是"first second third",也就是說#會把其後的符號直接加上雙引號。

##符號會連線兩個符號,從而產生新的符號(詞法層次),例如:

#define name( x ) name_##x

char* name( szlanny ); 巨集被展開後將成為:char* name_szlanny;

5.巨集中如有存在if等語句產生的分支,要使用do{}while(0)包起來,如

#define test(a ) if ( 0 == a ) dosomething()

如果在下面使用是會存在問題

if ( 1 == b)

test(a ):

else

那當**展開之後,巨集中的if與外面的else是一起匹配,而不是else與if ( 1 == b)匹配。

所以上述巨集要修改為 #define test(a ) do }while(0)

6.對於可變參巨集,可以使用__va_args__,gcc支援它,但並非所有的編譯器支援,如果你的**要跨平台,慎用。

#define log( format, ... ) printf( format, __va_args__ )

log( "%s %d", str, count );

__va_args__被自動替換為引數列表。

7.巨集不能巢狀使用,如

#define test( x ) ( x + test( x ) ) , 編譯器展開過程中發現第二個test,那麼就將這個test當作一般的符號。

8.當巨集的邏輯比較多時,可以考慮巨集中使用模板方法來代替巨集的邏輯實現。

如果,呼叫的時候,需要連線的符號,傳了字串。

會報 ,does not give a valid preprocessing token 。

expected initializer before string constant 。

C 中的巨集(續)

1.1.1.運算子 字元在 define巨集定義中是乙個將引數名轉換為字串的運算子,放在巨集引數的前面。例如 include include define declare non copiable begin cname class cname public virtual std string t...

c 中的巨集定義

一 不帶引數的巨集定義 巨集定義又稱為巨集代換 巨集替換,簡稱 巨集 格式 define 識別符號 字串 其中的識別符號就是所謂的符號常量,也稱為 巨集名 預處理 預編譯 工作也叫做巨集展開 將巨集名替換為字串。掌握 巨集 概念的關鍵是 換 一切以換為前提 做任何事情之前先要換,準確理解之前就要 換...

C中的巨集定義

01 防止乙個標頭檔案被重複包含 ifndef comdef h define comdef h 標頭檔案內容 endif 02 重新定義一些型別,防止由於各種平台和編譯器的不同,而產生的型別位元組數差異,方便移植。typedef unsigned char boolean boolean valu...