C語言的深入 了解程式編譯的過程 再談「巨集」

2021-09-29 07:18:58 字數 1338 閱讀 9686

一套**,在寫好執行的時候,其本身也是分好幾個步驟的。在windows下使用vs編譯看不到這樣的過程,而我們假如使用linux編譯,其過程就可以清楚的看清。

預處理階段

預處理完成之後就停下來,預處理之後產生的結果都放在test.i檔案,在該階段進行四項操作:

1、展開標頭檔案。

2、巨集替換。即我們在**中所寫的巨集,真正執行的時候是使用替換法。

3、去注釋。在編寫**的時候,為了使**閱讀性強,我們會加入一些注釋,但這些注釋對**本身是沒有作用的,因此在編譯的時候會將其去掉

4、條件編譯。這個與編寫者本身有關

編譯階段

在該階段主要進行**語法的檢查,如果編譯通過,生成彙編**,編譯完成之後就停下來,結果儲存在test.s中

彙編階段

在該階段將上一階段生成的彙編**轉換為二進位制的機器碼,彙編完成之後就停下來,結果儲存在test.o中

鏈結階段

每個目標檔案由鏈結器(linker)**在一起,形成乙個單一而完整的可執行程式。

在之前的學習中,我們在不少的地方都用到了巨集,本博文就這個問題再深入學習

1、#define機制包括了乙個規定,允許把引數替換到文字中。

例如:#define square(x) xx

在有了上述宣告後,使用square(5)就相當於55。

但注意,該寫法有著很大的漏洞

例如:square(5+1));第一眼看或許以為結果是36,但如果帶入變成了:5+15+1,答案11。

#define是乙個比較「笨」的員工,他只會按照要求搬運,因此在編寫巨集的時候一定要注意:在巨集定義上加上括號,這個問題便輕鬆的解決了

square(x) ( (x)(x) )

因此:所以用於對數值表示式進行求值的巨集定義都應該用這種方式加上括號,避免在使用巨集時由於引數中的操作符或鄰近操作符之間不可預料的相互作用。

2、巨集函式

巨集通常被應用於執行簡單的運算,而使用巨集不用函式,原因有這幾點

(1)使用函式法需要在棧上單獨開闢記憶體,因此需要更多的時間。

(2)函式的引數必須宣告型別,而巨集則不需要,它可以相容所有的型別

3、巨集的優點與缺點

優點:巨集最重要的優點就是增強**的復用性,其次因為巨集函式的存在還有減少棧開銷的效果

缺點:(1)每次使用巨集的時候,乙份巨集定義的**將插入到程式中。除非巨集比較短,否則可能大幅度增加程式的長度。

(2)巨集是沒法除錯的。

(3)巨集由於型別無關,也就不夠嚴謹。

(4)巨集可能會帶來運算子優先順序的問題,導致程容易出現錯。

本博文到此結束,感謝瀏覽

深入了解C語言

文章內容如下 首先,我們先來看下面這個經典的 int main 從這段 裡你看到了什麼問題?我們都知道,這段程式裡少了乙個 include 還少了乙個return 0 的返回語句。不過,讓我們來深入的學習一下,這段 在c 下無法編譯,因為c 需要明確宣告函式 這段 在c的編譯器下會編譯通過,因為在編...

深入了解C語言指標

目錄 注 指標的大小在32位平台是4個位元組,在64位平台是8個位元組。通過前面的知識我們知道,變數有不同的型別,如 整形,浮點型等。同理 指標也有不同的型別。指標的定義方式 變數型別 比如 int 程式設計客棧 pi null char pc null short ps null long pl ...

C 反射的深入了解

assembly.load 的使用說明如下 並不是命名空間。常用的是程式集名稱,也就是dll的名稱 關於反射assembly.load 程式集 createinstance 命名空間.類 而不管在哪一層寫這段 其中的 程式集 讀取的實際是web層bin資料夾下的dll,也就是說你反射的類的程式集dl...