C和指標(第14章 預處理器)

2021-09-09 05:10:08 字數 3060 閱讀 3667

程式編寫,編譯第一步就是巨集的宣告,也稱預處理器階段,在編譯之前,有刪除注釋,插入被#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.預定義符號 預處理器定義的符號,它們的值或者是字串常量,或者是十進位制數字常...