[mac-10.7.1 lion intel-based]
q: 預處理到底幹了什麼事情?
a: 預處理,顧名思義,預先做的處理。源**中的標頭檔案包含,巨集以及條件編譯的東西都會在預處理的時候搞定。換句話說,以#開頭的語句即為預處理。但是,如果#被包含在引號裡面,那就只是單純的字元或者字串了。
q: 怎麼證明預處理的存在?
a: 如下**,儲存為macro.c:
#include #define num 100
int main()
使用gcc -e macro.c -o macro.i得到預處理的結果(因為篇幅問題,只擷取最後數行**):
# 500 "/usr/include/stdio.h" 2 3 4
# 2 "macro.c" 2
int main()
可以看到,源**中的num已經被替換成了巨集定義的100.
事實上,預處理中的巨集同樣可以在命令列中指定,如下**,儲存為macro.c:
#include int main()
可以看到**中的num沒有被定義,然後使用編譯命令加上對num的巨集定義:
gcc -dnum=100 macro.c -o macro
編譯結束,沒有問題,執行亦ok.
同理,對於標頭檔案包含以及條件編譯都可以通過預處理命令得到處理之後的**形式,這樣會更好地理解預處理的含義。除錯巨集也不是乙個簡單的事情,如果很難確定某個巨集到底有沒有作用或者巨集對應的字串到底是什麼的時候,使用預處理命令得到結果是很好的方式。
q: 有時看到乙個字串前面帶有乙個#符號,它表示什麼含義?
形如:
#define print_ch(ch) printf(#ch" is %c\n", (ch));
a:它表示將對應字元組合轉換成相應的字串格式。
使用如下**,儲存為macro.c:
#include #define print_ch(ch) printf(#ch" is %c\n", (ch));
int main()
使用gcc -e -o macro.i macro.c編譯命令得到預處理後的檔案macro.i.
使用如下命令得到預處理檔案的最後10行:
可以看到print_ch('a')巨集被處理成: printf("'a'"" is %c\n", ('a'));
#ch的作用就是將它變成"ch"的模樣。兩個字串字面量放一起相當於字串拼接的作用。編譯和執行結果:
q: 除了上面的#符號,還會看到##符號,它又是什麼含義?
a: 它是代表引數連線,連線過程很單純,讓你看不到一點改變。舉個例子:
#include #define catenate(a, b) a##b
int main()
儲存為preprocess.c,預處理後的結果是(僅擷取最後數行**):
# 2 "preprocess.c" 2
int main()
編譯執行:
可以發現, a##b得到的結果就是ab這個符號。
q: 巨集定義也是可以續行的,為什麼有的時候用的反斜槓來續行,最後編譯依然有錯?
a: 這有可能續行符被用在了字串字面量裡面,這個不允許的;或者續行符後面跟著非換行字元導致的。續行的含義是將隨後緊隨的換行字元乾掉,當成沒發生,如果不是換行字元就可能導致錯誤。不過gcc 4.2對這個要求也不是很嚴格了,如下**,儲存為preprocess.c:
#include #define add(a, b) \
((a) + (b))
int main()
其中add巨集行末的續行符後面有乙個空格,在有的編譯器下會編譯錯誤。
為了確認續行符後面是否有空格,使用cat -e preprocess.c命令得到行末資訊:
可以看到第二行的續行符後面有個空格。編譯它,沒有什麼問題。
q: 看到printf函式是可變引數的,如果用巨集可以定義嗎?
a: 是的。__va_args__便是可變引數的代表。如下**:
#include #define printf_ex(...) printf(__va_args__)
int main (int argc, const char * argv)
上面的**巨集定義了printf_ex函式,引數為可變引數,它的實現即為printf函式,__va_args__即為printf_ex的可變引數。
編譯執行:
q: 既然可以巨集定義,那麼重複的巨集定義的結果是什麼呢?
a: 這樣的話,一般預處理器會按照後者定義的為準,不過一般的預處理器也會發出警告。
如下**,儲存為redefinition.c:
#include #define a 10
#define a 11
#define print_d(intvalue) printf(#intvalue" is %d\n", (intvalue));
int main (int argc, const char * argv)
編譯:
可以發現出現了a重複巨集定義的警告。
執行:
q: 有的時候發現需要列印當前執行的位置,比如檔名,行數以及執行所在的函式,這該怎麼辦?
a: 可以使用__file__, __line__和__func__這些預定義的符號來處理。這裡以__func__的使用為例子:
#include int add(int a, int b)
int main (int argc, const char * argv)
編譯執行:
可以看到add函式裡面的__func__被替換成了add.
xichen
2012-5-13 16:30:10
預處理,果然是預處理 小話c語言 5
mac 10.7.1 lion intel based q 預處理到底幹了什麼事情?a 預處理,顧名思義,預先做的處理。源 中的標頭檔案包含,巨集以及條件編譯的東西都會在預處理的時候搞定。換句話說,以 開頭的語句即為預處理。但是,如果 被包含在引號裡面,那就只是單純的字元或者字串了。q 怎麼證明預處...
C語言預處理
c語言中編譯預處理的三種形式的命令 巨集定義,檔案包含,條件編譯命令。1 巨集定義主要是 define,undef 如下 define pi 3.1415926 不帶引數的巨集定義 define max a,b a b?a b 帶引數的巨集定義 說明 巨集定義在c語言與c 語言中是相通的。下面舉例說...
C語言預處理
預處理 系統自動自動呼叫預處理程式對程式中 號開頭的預處理部分進行處理,處理完畢後可以進城源程式的編譯階段。預定義 一些預定義符號 常用於除錯 file 正在預編譯的源檔名 line 當前行號 只有這個是整數常量,其他是字串常量 function 當前所在函式名 date 當前日期 time 當前時...