程式編寫,編譯第一步就是巨集的宣告,也稱預處理器階段,在編譯之前,有刪除注釋,插入被#include指令包含的檔案的內容、和#define所替換的符號等。
14.1 五種預處理符號
__file__ ''name.c'' 進行編譯的源檔名
__line__ 25 檔案當前的行號
__date__ ''jan 14 2019'' 檔案被編譯的日期
__time__ ''11:32:07'' 檔案被編譯的時間
__stdc__ 1 如果編譯器遵循ansi c,其值就為1,否則未定義
file、line使用場景主要是在除錯程式時
date、time使用場景:在編譯後的程式中加入乙個時間標誌,區別程式的不同版本
stdc使用場景:當要求程式嚴格遵循ansi c標準時,識別符號__stdc__就會被賦值為1
14.2 巨集
注意:在使用巨集定義計算表示式如:
#define square(x) x*x
``````
square(5) // 5*5
而在下面情況下會產生意外:
error:
#define square(x) x*x
a = 5;
printf("%d\n",square(a+1)); // x*x預期結果為36
//而實際上 a+1*a+1 = 5+1*5+1 =11
right:
#define square(x) (x) * (x)
a = 5;
printf("%d\n",square(a+1)); // (x)*(x)結果為(5+1)*(5+1) = 36 正確
所以在用巨集定義一些計算表示式時需要注意符號之間的選擇,否則會產生不可預期的錯誤。
14.2.1 #與##
』#『的作用是將乙個巨集引數轉換為乙個字串
#define print(format,value) \
printf( the value of "#value" \
is "format"\n",value)
''''''
print("%d\n",x+3);
//將會輸出 the value of x+3 is 25
// 將x+3以字串的形式列印出
』##『的作用是把位於它兩邊的符號連線成乙個新的符號(這個新符號必須是有定義的,否則非法)
#define add_to_sum(sum_number, value) \
sum ## sum_number += value
''''''
'''add_to_sum(5, 25);
//將sum_number = 5 連線到sum後, 再將 value = 25 賦值給 sum5
14.2.3巨集與函式(1)巨集還可以用作簡單的計算,如比較兩個表示式中的較大值
#define max(a, b) ((a) > (b) ? (a): (b) )
其中用巨集完成這個計算功能比函式完成產生的**更少,所以在小型計算工作中,巨集的計算速度和程式規模都比函式要好;
更重要的是,函式必須宣告一種特定的資料型別,而巨集卻突破了這種限制,可以用整形,長整形,浮點數等,換句話說,巨集是與型別無關的。而需要注意的是,每次使用巨集時,乙份巨集定義**的拷貝都將插入到程式中,除非程式很短,否則使用巨集可能大幅度增加程式的長度。
(2)巨集可以完成函式無法完成的任務
#define malloc(n, type) \
( (type *)malloc( (n) * sizeof( type ) ) )
//可以定義型別為引數的巨集定義,而函式卻無法完成
但不合理的使用巨集引數將會產生***,比如:
x+1執行幾百萬次每次得到的結果都相同 而x++執行超過一次之後,每執行一次x的值將發生變化,到最後每個**段**現一次x之變化一次,直至最後x的值無法確定。
14.3 條件編譯
這部分簡單了解 首先給出語法形式:
#if constant-expression(常量表示式)
statements
#endif
14.4 檔案包含
編譯器支援兩種不同型別的#include檔案包含:
1. #include(處理呼叫函式庫中的檔案)
2.#include "filename" (處理本地標頭檔案)
巢狀檔案包含:在很多的大型程式中,往往包含了很多的標頭檔案,而為了不重複呼叫同一標頭檔案,可以用下面語法形式定義減少重複定義:
#ifndef __headername_h
#define __headername_h 1
#endif
14.7 警告的總結
1.不要在乙個巨集定義的末尾加上分號,使其成為一條完整的語句。
2.在巨集定義中使用引數,但忘了在它們周圍加上括號。
3.忘了在整個巨集定義的兩邊加上括號。
14.8程式設計提示的總結
1.避免用#define指令定義可以用函式實現很長序列的**。
2.在那些對表示式求值的巨集中,每個巨集引數出現的地方都應該加上括號,並且在整個巨集定義的兩邊也加上括號。
3.採用命名約定,使程式設計師很容易看出某個識別符號是否為#define巨集。
5.只要適合就應該使用檔案包含,不必擔心它的額外開銷。
《C和指標》第14章 預處理器
14.2.1 巨集 define包括乙個規定,允許把引數替換到文字中,這種實現通常稱為巨集 macro define square x x x 則程式中的square 5 會被替換成 5 5 警告 例1 a 5 printf d n square a 1 會被替換成5 1 5 1,列印結果是11,不...
第14章 預處理器
c預處理器在源 編譯之前對其進行一些文字性質的操作。它的主要任務包括刪除注釋 插入被 include指令包含的檔案的內容 定義和替換由 define指令定義的符號以及確定 的部分內容是否應該根據一些條件編譯指令進行編譯。在 define中,如果定義的內容很長,可以分成幾行,除了最後一行之外,每行的末...
C和指標 學習筆記 第14章 預處理器
c預處理器在源 編譯之前對其進行一些文字性質的操作。它的主要任務包括刪除注釋 插入被 include指令包含的檔案的內容 定義和替換由 define指令定義的符號以及確定 的部分內容是否應該根據一些條件編譯指令進行編譯。1.預定義符號 預處理器定義的符號,它們的值或者是字串常量,或者是十進位制數字常...