生成一個可執行的文件一般須要通過如下幾個步驟:前端
預處理你的源代碼,去掉註釋,以及其餘技巧性的工做就像在 C 中展開宏。函數
檢查代碼的語法看你是否遵照了這個語言的規則。若是沒有,編譯器會給出 警告。測試
把源代碼轉換爲彙編語言 ── 和機器代碼很類似, 可是在必定狀況下咱們仍然能夠理解。 [1]優化
把彙編語言轉換爲機器語言──是的,咱們在說位元和字節,就是1和0。spa
檢查你是否準確地使用了函數和全局變量相似的東西。例如,若是你調用了一個不存在的函數,編譯器就會給出警告。命令行
若是你是從多個源代碼文件編譯,就要學會如何把這些文件組合到一塊兒。debug
把產生出來的東西用系統的運行裝載器裝入內存並運行。調試
最後,把可執行文件寫入文件系統。code
編譯 這個詞的意思一般指 1 到 4 步──其餘的 步驟叫作 鏈接。有時侯第一步叫作 預處理 。第三和第四步叫作 彙編 。排序
幸運的是,幾乎全部這些細節都是隱藏的,由於 cc 只是一個前端。它根據正確的參數調用程序來處理代碼。只要輸入
%
cc foobar.c
就會把 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
編譯。
這會產生一個可調試版本的程序。 [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
當出現多個優化時,以最後一個爲準!!
可指定查找include文件的其餘位置.例如,若是有些include文件位於比較特殊的地方,好比/usr/local/include,就能夠增長此選項以下:
$cc -c -I/usr/local/include -I/opt/include hello.c
此時目錄搜索會按給出的次序進行.
這個選項是相對標準的,它容許修改命令行以使編譯程序把預先處理的C文件發到標準輸出,而不實際編譯代碼.在查看C預處理僞指令和C宏時,這是頗有用的.可能的編譯輸出可從新定向到一個文件,而後用編輯程序來分析:
$cc -c -E hello.c >cpp.out
此命令使include文件和程序被預先處理並重定向到文件cpp.out.之後能夠用編輯程序或者分頁命令分析這個文件,並肯定最終的C語言代碼看起來如何.
-D
容許從編譯程序命令行定義宏符號
一共有兩種狀況:一種是用-DMACRO,至關於在程序中使用#define MACRO,另外一種是用-DMACRO=A,至關於
#ifdefine DEBUG
printf("debug message\n");
#endif
編譯時可加上-DDEBUG參數,執行程序則打印出編譯信息
下面的三個參數會迫使 cc 檢查你的代碼是否符合一些國際標準,常常被咱們叫作 ANSI 標準,雖然嚴格的來講它是一個 ISO 標準。
-Wall
打開全部 cc 的做者認爲值得注意的警告。不要只看這個選項的名字,它並無打開全部 cc 可以注意到的全部警告。
-ansi
關閉大多數,但並非全部,cc 提供的非 ANSI C 特性。不要只看選項的名字,它並不嚴格保證你的代碼會兼容標準。
-pedantic
關閉 全部 cc 的非 ANSI C 特性。
沒有這些選項,cc 能容許你按照標準使用一些非標準的擴展。有一些擴展很是有用,但不能與其餘編譯器兼容──實際上,這個標準的主要目的之一就是容許咱們寫出能夠在任何系統上的由任何編譯器編譯的代碼。這就叫作 可移植代碼
一般來講,你應該讓你的代碼儘量的能夠移植。不然你就不得不徹底重寫你的代碼以便可以在其餘地方運行之──並且誰知道幾年後你是否還會用它?