C語言預處理功能 關於字符串化和符號粘貼

在C語言開發中,宏定義是一個很是有用的工具,它能夠使咱們的代碼更容易理解,更容易維護。如查一個常量在多處被使用,且從此可能會根據不一樣須要而 修改的話,將其define一下那是再好不過了。除此以外,宏定義還有其餘的功能,瞭解它,將更好地輔助咱們開發C程序。先看個例子:工具

#define Conn(x,y)測試

x##y.net

#define ToString(x)調試

#xip

#define ToChar(x)開發

#@x 字符串

這幾個宏定義中分別用到了「##」、「#」,「#@」它們的功能分別是:get

一、粘接操做符##——鏈接兩個宏名,注意所鏈接的是宏名,而不是其所指代的值;編譯器

如int Conn(a,b);定義了一個int型變量ab,之後能夠直接調用ab,而沒必要採用Conn(a,b)的形式;string

printf(Conn("ab","cd"));輸出結果爲:abcd

可是:

#define M 0 #define var(x) Var_##x ... int var(M);//此處定義了什麼?

根據ANSI/ISO C,##操做符只是簡單地粘接兩個宏名,則int var(M)定義的應該就是Var_M,據測試,這一點是沒有問題的。但在一些比較古老的C編譯環境中,也有可能定義的是Var_0,好比在TC 2.0中測試發現「Var_0=0」可編譯經過,而「Var_M=0」出現ERROR。

二、字符串化操做符#——將宏名轉化爲字符串

如printf(ToString(var1));輸出結果爲:var1。var1能夠是一個已定義的變量名,也能夠是一個從未出現的字符組合

相似地,如有:

#define STR 0

...

printf(Tostring(STR));//

當前流行編譯環境會輸出STR,而TC 2.0則會輸出0。

三、字符化操做#@——將宏名轉化爲字符,注意:早期編譯器可能不支持

如:

char c;

c = ToChar(1);//c = '1'

c = ToChar(a);//c = 'a'

若是提供的宏中不止一個字符(注意,不能超過4個,不然編譯器報錯),則轉化結果爲最後一個字符,如

c = ToChar(abc);//c = 'c'

c = ToChar(abcd);//c= 'd'

c = ToChar(abcde);//ERROR

總結一下,關於其用法是本身總結的,確定不全。

一、使用中遵循ANSI C中規定,但要記得編譯通不過是多是早期編譯器不支持C標準的問題;

二、##操做可應用在變量定義中,若程序開發中遇到要定義一大堆變量,且這些變量具備相同的前綴時,##很顯得尤其重要,它能夠使代碼更加整潔,且減小了出錯的機率。若是一旦後來發現須要批量修改變量前綴,你會慶幸本身使用了這麼一件利器;

三、#操做符可用於調試時將變量名輸出,可配合##一塊兒使用,如定義#define CHECK_VAR(x,fmt) printf(#x " = " #fmt "\n", x),則CHECK_VAR(var1,%d)至關於printf("var = %d\n", var1);

Tips:

一、ANSI C中規定若宏定義名出如今引號(' '或" ")中,則不進行替換,但有些早期編譯器的處理可能有所不一樣,如#define CTRL(c) (‘c’ & 37),按照標準CTRL(d)被擴展成('c' & 37)。顯然,這沒有完成做者的本意,它在某些編譯器下碰巧能工做不過是個意外,實際使用中應避免。

二、字符串的鏈接沒必要使用##這麼麻煩,實際中兩個字符串常量能夠直接寫到一塊兒,如printf("ab""cd")輸出abcd。或在使 用##宏定義時,能夠用printf(ToString(str) "\n");輸出字符串後換行,之前不敢這樣用,後來試驗了下發現還比較好使,固然直接用puts也可完成一樣功能。

三、若要使#或##轉換的是宏字符常量的值也不是其名字,能夠使用間接方法,如:

#define ToString(x) #x

#define Xstr(x) ToString(x)

#define STR1 STR2 ...

printf(Xstr(STR1));//輸出結果是STR2而非STR1

相關文章
相關標籤/搜索