預先處理還需要運算子?有沒有搞錯?
^_^, 沒有搞錯,預先處理是有運算子,而且還不止一個:
- #
(單井號) —— 字串化運算子。
- ##
(雙井號 )—— 串連運算子
- #@
—— 字元化運算子。
接下來我們會分別說明一下他們的用法.
1.字串化運算子 ——
#
用於建立字串,#運算子後面應該跟一個形參(中間可以有空格或Tab),例如:
#define STR(s) #s<br /> puts(STR(Here is a Demo)); // 相當於puts("Here is a Demo");<br />
常用執行個體:
我們在調試代碼的時候有時需要列印一些字串的值,如下:
#include<stdio.h>#define Dump_Str(s) printf("%s = %s/n",#s,s); int main(){ const char * pchName = "Gui xue"; Dump_Str(pchName);} 2.串連運算子 ——
##
用於將兩個Token串連成一個Token; 這裡提到一個需要概念Token ,
先說明一下:
什麼是Token?
人與人之間的溝通,通過說話,而每句話便是由單詞
組合在一起,形成特定的語義
。這裡的單詞便可理解成
Token。
C語言編譯器相當於一個翻譯,要懂兩種語言——C語言和機器語言;它的工作是將C語言翻譯成機器語言。首先它應該讀懂C語言中的“句子”,而對整個“句子”的理解,是建立在對每個“單詞”理解的基礎上的,所以首先我們要把句子分成多個單詞——分詞。
詞法分析便是將C語言的“句子”按照詞法規則拆分成 Token 序列。
例如:
#define __CONCAT(x,y)x ## y<br />int n1 =15;<br />int n2 =200;<br />__CONCAT(n,1); // n1<br />__CONCAT(n,2); // n2<br />
常見用法:glib庫中
stdint.h (sysdeps/generic):150:
#define __INT64_C(c) c
## L
stdint.h (sysdeps/generic):151:
#define
__UINT64_C(c) c ## UL
將某個常量後自動加上 L或UL,達到資料類型強制轉換的目的。
3.字元化運算子——
#@
用於建立一個字元,類似 ## ,註: 非 ANSI-C中的特性,GCC不支援,VC可以; 使用執行個體如下:
#include<stdio.h>#define Dump_Char(c) #@cint main(){ printf("%c/n",Dump_Char(g));//gprintf("%c/n",Dump_Char(guix));//x 可以輸入 4個長度的字元,但只輸出最後一位printf("%c/n",Dump_Char( guix ));//x 預設去除前後空格,保留中間空格printf("%c/n",Dump_Char(guixu));//error C2015: too many characters in constant}
轉載請註明:來自Come to See-See!