生成乙個可執行的檔案通常需要經過以下幾個步驟:
預處理你的源**,去掉注釋,以及其他技巧性的工作就像在 c 中展開巨集。
檢查**的語法看你是否遵守了這個語言的規則。如果沒有,編譯器會給出 警告。
把源**轉換為組合語言 ── 和機器**很相似, 但是在一定情況下我們仍然可以理解。 [1]
把組合語言轉換為機器語言──是的,我們在說位元和位元組,就是1和0。
檢查你是否準確地使用了函式和全域性變數類似的東西。例如,如果你呼叫了乙個不存在的函式,編譯器就會給出警告。
如果你是從多個源**檔案編譯,就要學會如何把這些檔案組合到一起。
把產生出來的東西用系統的執行裝載器裝入記憶體並執行。
最後,把可執行檔案寫入檔案系統。
編譯 這個詞的意思通常指 1 到 4 步──其他的 步驟叫做 連線。有時侯第一步叫做 預處理 。第三和第四步叫做 彙編 。
幸運的是,幾乎所有這些細節都是隱藏的,因為 cc 只是乙個前端。它根據正確的引數呼叫程式來處理**。只要輸入
%cc foobar.c %
cc foo.c bar.c
注意,語法檢查就是──純粹的檢查語法。而不會檢測你可能犯的任何邏輯錯誤。比如無限迴圈,或者是你想用一元排序卻使用了氣泡排序。 [2]
cc 有很多選項,在幫助手冊中都可以找到。這裡列出了一些最重要的選項,並且有例子。
-o filename
輸出的檔名。如果你不使用這個選項,cc為產生 出乙個叫 a.out 的執行檔案。 [3]
%cc foobar.c 可執行檔案是
a.out
%cc -o foobar foobar.c 可執行檔案是
foobar
-c
僅僅編譯檔案,不會連線。如果你只想檢查你寫的測試程式的語法的話,這個選項非常有用。或者你會使用 makefile。
%cc -c foobar.c
這會產生乙個 目標檔案 (不可執行) 叫做 foobar.o。這個檔案可以和其他的目標檔案連線在一起構成乙個可執行檔案。
-g
產生乙個可除錯的可執行檔案。編譯器會在可執行檔案中植入一些資訊,這些資訊能夠把原始檔中的行數和被呼叫的函式聯絡起來。在你一步一步除錯程式的時候,偵錯程式能夠使用這些資訊來顯示源**。這是 非常 有用的;缺點就是被植入的資訊讓程式變得更大。通常情況下,開 發乙個程式的時候我們經常使用-g
,但是我們在編譯乙個 「release 版本」 的程式的時候,如果程式工作得讓人滿意了,我 們就不使用-g
編譯。
%cc -g foobar.c
這會產生乙個可除錯版本的程式。 [4]
-o
產生乙個優化版本的可執行檔案。編譯器會使用一些聰明的技巧產生出比普通編譯產生的檔案執行更快的可執行檔案。可以在-o
加上數字來使用更高階的優化。但是這樣做經常會暴露出編譯器的優化器中的一些 錯誤。例如,2.1.0 版本的 freebsd 中的 cc 在某些情況 下使用了-o2
的話,會產生出錯誤的**。
優化通常只在編譯乙個 release 版本的時候才被開啟。
%cc -o -o foobar foobar.c
這會產生乙個優化版本的 foobar。
-o和 -o1指定1級優化
-o2 指定2級優化
-o3 指定3級優化
-o0指定不優化
$cc -c o3 -o0 hello.c
當出現多個優化時,以最後乙個為準!!
-i可指定查詢include檔案的其他位置.例如,如果有些include檔案位於比較特殊的地方,比如/usr/local/include,就可以增加此選項如下:
$cc -c -i/usr/local/include -i/opt/include hello.c
此時目錄搜尋會按給出的次序進行.
-e這個選項是相對標準的,它允許修改命令列以使編譯程式把預先處理的c檔案發到標準輸出,而不實際編譯**.在檢視c預處理偽指令和c巨集時,這是很有用的.可能的編譯輸出可重新定向到乙個檔案,然後用編輯程式來分析:
$cc -c -e hello.c >cpp.out
此命令使include檔案和程式被預先處理並重定向到檔案cpp.out.以後可以用編輯程式或者分頁命令分析這個檔案,並確定最終的c語言**看起來如何.
-d
允許從編譯程式命令列定義巨集符號
一共有兩種情況:一種是用-dmacro,相當於在程式中使用#define macro,另一種是用-dmacro=a,相當於
程式中的#define macro a.如對下面這**:
#ifdefine debug
printf("debug message\n");
#endif
編譯時可加上-ddebug引數,執行程式則列印出編譯資訊
下面的三個引數會迫使 cc 檢查你的**是否符合一些國際標準,經常被我們叫做 ansi 標準,雖然嚴格的來說它是乙個 iso 標準。
-wall
開啟所有 cc 的作者認為值得注意的警告。不要只看這個選項的名字,它並沒有開啟所有 cc 能夠注意到的所有警告。
-ansi
關閉大多數,但並不是所有,cc 提供的非 ansi c 特性。不要只看選項的名字,它並不嚴格保證你的**會相容標準。
-pedantic
關閉 所有
cc 的非 ansi c 特性。
沒有這些選項,cc 能允許你按照標準使用一些非標準的擴充套件。有一些擴充套件非常有用,但不能與其他編譯器相容──實際上,這個標準的主要目的之一就是允許我們寫出可以在任何系統上的由任何編譯器編譯的**。這就叫做 可移植**
通常來說,你應該讓你的**盡可能的可以移植。否則你就不得不完全重寫你的**以便能夠在其他地方執行之──而且誰知道幾年後你是否還會用它?
C C 語言編譯過程
2.編譯 優化過程 將.i檔案翻譯成會變得彙編 s檔案 在windows中,通常使用.asm便是彙編檔案 具體過程 詞法分析 語法分析 語義分析 中間 生成 優化 生成 將多個步驟組合成趟 編譯器構成工具 ps 這裡解釋一下 趟 的概念 這個 趟 指的是對源程式或者其等價的中間 語言程式進行從頭到尾...
C C 編譯原理及過程整理
面試被問到c編譯原理,所以回來整理一下。編譯主要分為四個大步驟 預編譯 編譯 s asm 彙編 obj o a ko 鏈結 exe elf axf等 在c c 中統稱為編譯。前面文章 介紹過整合開發環境 編譯器,這裡再說明一下,整合開發環境是用於提供程式開發環境的應用程式,一般包括 編輯器 編譯器,...
C語言的編譯過程
乙個源程式執行得到結果一般都要經過編譯和執行的過程,c語言的編譯和執行過程如下 編譯的過程 編譯的功能是將人們能看懂的高階語言,轉換成計算機能看懂的二進位制語言,可以分為下面的六個階段 乙個原始檔經過上述的6個過程即可轉化成目標 檔案,把高階語言轉化成機器語言。c語言編譯的完整過程如下圖 1 編譯預...