define 的深度剖析

2021-07-23 19:40:01 字數 1885 閱讀 8207

1.預處理識別符號的使用:

#include#define __file__    //進行編譯的原始檔

#define __line__ //檔案當前的行號

#define __date__ //檔案被編譯的日期

#define __time__ //檔案被編譯的時間

int main()

執行結果:

這樣可以輸出當前編譯檔案的相關資訊,使用非常方便。

2.了解巨集和函式的區別

使用巨集的語法和使用函式的語法是完全一樣的,所以語言本身不能區分這兩者,一般情況下,我們將巨集的名字全部用大寫來區分。

巨集可以非常頻繁的用於執行簡單的計算,比如:

#define max(a,b)     ((a)>(b)?(a):(b))             //求兩個數中較大的乙個

為什麼不用函式來完成,有兩個原因:

1)用於呼叫和函式返回的**很可能比實際執行這個小型計算工作的代價大,所以使用巨集比使用函式在程式的規模和速度更勝一籌。

2)但是更重要的是,函式的引數必須申明為一種特定的型別,所以函式只能在型別合適的表示式上使用。反之,巨集可以用於整形、長整形......以及其他任何可以使用》操作符

比較大小的型別。

巨集是和型別無關的。

和函式相比,使用巨集的不好處在於每次使用時,都要將巨集定義的**拷貝到程式中,除非巨集非常短,否則使用巨集可能會大幅度增加程式的長度。

還有一些任務函式無法實現,比如:

#include#define malloc(n,type) ((type*)malloc((n)*sizeof(type)))

int main()

這個程式經過預處理後得到:

int main()

這個巨集的第二個引數是一種型別,它無法作為函式引數進行傳遞。

3.巨集引數的***

當巨集引數在巨集定義中出現次超過一次時,如果這個引數具有***,那麼使用時就有可能導致不可預料的結果。比如

x++;

#include#define max(a,b)   ((a)>(b)?(a):(b))

int main()

得到結果:

在這個程式中較小值計算了一次,但是較大值卻計算了兩次。

4.編譯鏈結的整個過程

1)預處理過程

(1)巨集替換

(2)標頭檔案展開

(3)取消注釋

(4)條件編譯

在編譯乙個程式時,如果我們可以選擇某條語句或某組語句進行翻譯或者被忽略,就會很方便,條件編譯就是用於實現這個目的的。

2)編譯過程(c程式**到彙編)

3)彙編過程(彙編到二進位制)

4)鏈結過程(將二進位制生成可執行程式的過程)

比如:

#include#define debug 1                  //debug被定義則執行語句,值為1時執行,為0時不執行

#define realse 1

int main()

執行結果:

可以通過更改定義的值debug,realse來選擇執行哪條語句,可以起到很好的除錯作用。

指標的深度剖析

在c語言中,指標 pointer 是程式語言中的乙個物件,利用位址,它的值直接指向存在電腦儲存器中另乙個地方的值。由於通過位址能找到所需的變數單元,可以說,位址指向該變數單元。因此,將位址形象化的稱為 指標 意思是通過它能找到以它為位址的記憶體單元。指標變數和指標 將乙個變數的位址稱為變數的指標,存...

ifdef cplusplus深度剖析

時常在cpp的 之中看到這樣的 ifdef cplusplus extern c endif 這樣的 到底是什麼意思呢?首先,cplusplus是cpp中的自定義巨集,那麼定義了這個巨集的話表示這是一段cpp的 也就是說,上面的 的含義是 如果這是一段cpp的 那麼加入extern c 處理其中的 ...

深度剖析ostream

雖然c 學了大半個月了,自己學了解了很多關於c 的知識,大的概念懂了不少,但是還是想說想要徹底的弄懂c 絕非易事。當別人問到乙個很小的知識點些許你都要愣很久,事實告訴我們不能太好高騖遠。為什麼要寫ostream而不是istream,因為當我們自定義型別 student類 的時候,如果需要輸出 stu...