<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 21.2 使用傳統程序語言進行編譯的簡單范例 經過上面的介紹之后,你應該比較清楚的知道源代碼、編譯器、函數庫與可執行文件之間的相關性了。 不過,詳細的流程可能還是不很清楚,所以,在這里我們以一個簡單的程序范例來說明整個編譯的過程喔!趕緊進入 Linux 系統,實地的操作一下下面的范例呢! ### 21.2.1 單一程序:印出 Hello World 我們以 Linux 上面最常見的 C 語言來撰寫第一支程序!第一支程序最常作的就是..... 在屏幕上面印出“Hello World!”的字樣~當然, 這里我們是以簡單的 C 語言來撰寫,如果你對于 C 有興趣的話,那么請自行購買相關的書籍喔! ^_^ 好了,不啰唆,立刻編輯第一支程序吧! ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 請先確認你的 Linux 系統里面已經安裝了 gcc 了喔!如果尚未安裝 gcc 的話,請先參考下一節的 RPM 安裝法,先安裝好 gcc 之后,再回來閱讀本章。 如果你已經有網絡了,那么直接使用“ yum groupinstall "Development Tools" ” 預先安裝好所需的所有軟件即可。 rpm 與 yum 均會在下一章介紹。 * 編輯程序碼,亦即源代碼 ``` [root@study ~]# vim hello.c &lt;==用 C 語言寫的程序擴展名建議用 .c #include &lt;stdio.h&gt; int main(void) { printf("Hello World\n"); } ``` 上面是用 C 語言的語法寫成的一個程序文件。第一行的那個“ # ”并不是注解喔!如果你擔心輸入錯誤, 請到下面的鏈接下載這個文件: * [http://linux.vbird.org/linux_basic/0520source/hello.c](http://linux.vbird.org/linux_basic/0520source/hello.c) * 開始編譯與測試執行 ``` [root@study ~]# gcc hello.c [root@study ~]# ll hello.c a.out -rwxr-xr-x. 1 root root 8503 Sep 4 11:33 a.out &lt;==此時會產生這個文件名 -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c [root@study ~]# ./a.out Hello World &lt;==呵呵!成果出現了! ``` 在默認的狀態下,如果我們直接以 gcc 編譯源代碼,并且沒有加上任何參數,則可執行文件的文件名會被自動設置為 a.out 這個文件名稱! 所以你就能夠直接執行 ./a.out 這個可執行文件啦!上面的例子很簡單吧!那個 hello.c 就是源代碼,而 gcc 就是編譯器,至于 a.out 就是編譯成功的可執行 binary program 啰! 咦!那如果我想要產生目標文件 (object file) 來進行其他的動作,而且可執行文件的文件名也不要用默認的 a.out ,那該如何是好?其實你可以將上面的第 2 個步驟改成這樣: ``` [root@study ~]# gcc -c hello.c [root@study ~]# ll hello* -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c -rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o &lt;==就是被產生的目標文件 [root@study ~]# gcc -o hello hello.o [root@study ~]# ll hello* -rwxr-xr-x. 1 root root 8503 Sep 4 11:35 hello &lt;==這就是可可執行文件! -o 的結果 -rw-r--r--. 1 root root 71 Sep 4 11:32 hello.c -rw-r--r--. 1 root root 1496 Sep 4 11:34 hello.o [root@study ~]# ./hello Hello World ``` 這個步驟主要是利用 hello.o 這個目標文件制作出一個名為 hello 的可執行文件,詳細的 gcc 語法我們會在后續章節中繼續介紹!通過這個動作后,我們可以得到 hello 及 hello.o 兩個文件, 真正可以執行的是 hello 這個 binary program 喔! 或許你會覺得,咦!只要一個動作作出 a.out 就好了,干嘛還要先制作目標文件再做成可執行文件呢? 呵呵!通過下個范例,你就可以知道為什么啦! ### 21.2.2 主、副程序鏈接:副程序的編譯 如果我們在一個主程序里面又調用了另一個副程序呢?這是很常見的一個程序寫法, 因為可以簡化整個程序的易讀性!在下面的例子當中,我們以 thanks.c 這個主程序去調用 thanks_2.c 這個副程序,寫法很簡單: * 撰寫所需要的主、副程序 ``` # 1\. 編輯主程序: [root@study ~]# vim thanks.c #include &lt;stdio.h&gt; int main(void) { printf("Hello World\n"); thanks_2(); } # 上面的 thanks_2(); 那一行就是調用副程序啦! [root@study ~]# vim thanks_2.c #include &lt;stdio.h&gt; void thanks_2(void) { printf("Thank you!\n"); } ``` 上面這兩個文件你可以到下面下載: * [http://linux.vbird.org/linux_basic/0520source/thanks.c](http://linux.vbird.org/linux_basic/0520source/thanks.c) * [http://linux.vbird.org/linux_basic/0520source/thanks_2.c](http://linux.vbird.org/linux_basic/0520source/thanks_2.c) * 進行程序的編譯與鏈接 (Link) ``` # 2\. 開始將源代碼編譯成為可執行的 binary file : [root@study ~]# gcc -c thanks.c thanks_2.c [root@study ~]# ll thanks* -rw-r--r--. 1 root root 75 Sep 4 11:43 thanks_2.c -rw-r--r--. 1 root root 1496 Sep 4 11:43 thanks_2.o &lt;==編譯產生的! -rw-r--r--. 1 root root 91 Sep 4 11:42 thanks.c -rw-r--r--. 1 root root 1560 Sep 4 11:43 thanks.o &lt;==編譯產生的! [root@study ~]# gcc -o thanks thanks.o thanks_2.o [root@study ~]# ll thanks* -rwxr-xr-x. 1 root root 8572 Sep 4 11:44 thanks &lt;==最終結果會產生這玩意兒 # 3\. 執行一下這個文件: [root@study ~]# ./thanks Hello World Thank you! ``` 知道為什么要制作出目標文件了嗎?由于我們的源代碼文件有時并非僅只有一個文件,所以我們無法直接進行編譯。 這個時候就需要先產生目標文件,然后再以鏈接制作成為 binary 可可執行文件。另外,如果有一天,你更新了 thanks_2.c 這個文件的內容,則你只要重新編譯 thanks_2.c 來產生新的 thanks_2.o ,然后再以鏈接制作出新的 binary 可可執行文件即可!而不必重新編譯其他沒有更動過的源代碼文件。 這對于軟件開發者來說,是一個很重要的功能,因為有時候要將偌大的源代碼全部編譯完成,會花很長的一段時間呢! 此外,如果你想要讓程序在執行的時候具有比較好的性能,或者是其他的除錯功能時, 可以在編譯的過程里面加入適當的參數,例如下面的例子: ``` [root@study ~]# gcc -O -c thanks.c thanks_2.c &lt;== -O 為產生最優化的參數 [root@study ~]# gcc -Wall -c thanks.c thanks_2.c thanks.c: In function ‘main’: thanks.c:5:9: warning: implicit declaration of function ‘thanks_2’ [-Wimplicit-function-declaration] thanks_2(); ^ thanks.c:6:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ # -Wall 為產生更詳細的編譯過程信息。上面的訊息為警告訊息 (warning) 所以不用理會也沒有關系! ``` 至于更多的 gcc 額外參數功能,就得要 man gcc 啰~呵呵!可多的跟天書一樣~ ### 21.2.3 調用外部函數庫:加入鏈接的函數庫 剛剛我們都僅只是在屏幕上面印出一些字眼而已,如果說要計算數學公式呢?例如我們想要計算出三角函數里面的 sin (90度角)。要注意的是,大多數的程序語言都是使用徑度而不是一般我們在計算的“角度”, 180 度角約等于 3.14 徑度!嗯!那我們就來寫一下這個程序吧! ``` [root@study ~]# vim sin.c #include &lt;stdio.h&gt; #include &lt;math.h&gt; int main(void) { float value; value = sin ( 3.14 / 2 ); printf("%f\n",value); } ``` 上面這個文件的內容可以在下面取得! * [http://linux.vbird.org/linux_basic/0520source/sin.c](http://linux.vbird.org/linux_basic/0520source/sin.c) 那要如何編譯這支程序呢?我們先直接編譯看看: ``` [root@study ~]# gcc sin.c # 新的 GCC 會主動將函數抓進來給你用,所以只要加上 include &lt;math.h&gt; 就好了! ``` 新版的 GCC 會主動幫你將所需要的函數庫抓進來編譯,所以不會出現怪異的錯誤訊息! 事實上,數學函數庫使用的是 libm.so 這個函數庫,你最好在編譯的時候將這個函數庫納進去比較好~另外要注意, 這個函數庫放置的地方是系統默認會去找的 /lib, /lib64 ,所以你無須使用下面的 -L 去加入搜尋的目錄! 而 libm.so 在編譯的寫法上,使用的是 -lm (lib 簡寫為 l 喔!) 喔!因此就變成: * 編譯時加入額外函數庫鏈接的方式: ``` [root@study ~]# gcc sin.c -lm -L/lib -L/lib64 &lt;==重點在 -lm [root@study ~]# ./a.out &lt;==嘗試執行新文件! 1.000000 ``` 特別注意,使用 gcc 編譯時所加入的那個 -lm 是有意義的,他可以拆開成兩部份來看: * -l :是“加入某個函數庫(library)”的意思, * m :則是 libm.so 這個函數庫,其中, lib 與擴展名(.a 或 .so)不需要寫 所以 -lm 表示使用 libm.so (或 libm.a) 這個函數庫的意思~至于那個 -L 后面接的路徑呢?這表示: “我要的函數庫 libm.so 請到 /lib 或 /lib64 里面搜尋!” 上面的說明很清楚了吧!不過,要注意的是,由于 Linux 默認是將函數庫放置在 /lib 與 /lib64 當中,所以你沒有寫 -L/lib 與 -L/lib64 也沒有關系的!不過,萬一哪天你使用的函數庫并非放置在這兩個目錄下,那么 -L/path 就很重要了!否則會找不到函數庫喔! 除了鏈接的函數庫之外,你或許已經發現一個奇怪的地方,那就是在我們的 sin.c 當中第一行“ #include &lt;stdio.h&gt;”,這行說的是要將一些定義數據由 stdio.h 這個文件讀入,這包括 printf 的相關設置。這個文件其實是放置在 /usr/include/stdio.h 的!那么萬一這個文件并非放置在這里呢?那么我們就可以使用下面的方式來定義出要讀取的 include 文件放置的目錄: ``` [root@study ~]# gcc sin.c -lm -I/usr/include ``` -I/path 后面接的路徑( Path )就是設置要去搜尋相關的 include 文件的目錄啦!不過,同樣的,默認值是放置在 /usr/include 下面,除非你的 include 文件放置在其他路徑,否則也可以略過這個項目! 通過上面的幾個小范例,你應該對于 gcc 以及源代碼有一定程度的認識了,再接下來,我們來稍微整理一下 gcc 的簡易使用方法吧! ### 21.2.4 gcc 的簡易用法 (編譯、參數與鏈結) 前面說過, gcc 為 Linux 上面最標準的編譯器,這個 gcc 是由 [GNU 計劃](http://www.gnu.org/)所維護的,有興趣的朋友請自行前往參考。既然 gcc 對于 Linux 上的 Open source 是這么樣的重要,所以下面我們就列舉幾個 gcc 常見的參數,如此一來大家應該更容易了解源代碼的各項功能吧! ``` # 僅將源代碼編譯成為目標文件,并不制作鏈接等功能: [root@study ~]# gcc -c hello.c # 會自動的產生 hello.o 這個文件,但是并不會產生 binary 可執行文件。 # 在編譯的時候,依據作業環境給予最優化執行速度 [root@study ~]# gcc -O hello.c -c # 會自動的產生 hello.o 這個文件,并且進行最優化喔! # 在進行 binary file 制作時,將鏈接的函數庫與相關的路徑填入 [root@study ~]# gcc sin.c -lm -L/lib -I/usr/include # 這個指令較常下達在最終鏈接成 binary file 的時候, # -lm 指的是 libm.so 或 libm.a 這個函數庫文件; # -L 后面接的路徑是剛剛上面那個函數庫的搜尋目錄; # -I 后面接的是源代碼內的 include 文件之所在目錄。 # 將編譯的結果輸出成某個特定文件名 [root@study ~]# gcc -o hello hello.c # -o 后面接的是要輸出的 binary file 文件名 # 在編譯的時候,輸出較多的訊息說明 [root@study ~]# gcc -o hello hello.c -Wall # 加入 -Wall 之后,程序的編譯會變的較為嚴謹一點,所以警告訊息也會顯示出來! ``` 比較重要的大概就是這一些。另外,我們通常稱 -Wall 或者 -O 這些非必要的參數為旗標 (FLAGS),因為我們使用的是 C 程序語言,所以有時候也會簡稱這些旗標為 CFLAGS ,這些變量偶爾會被使用的喔!尤其是在后頭會介紹的 make 相關的用法時,更是重要的很吶! ^_^
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看