講解第一支C程式

上一堂課我們安裝了GCC編譯器,並建立了最簡單的 hello world 範例,這堂課我們來逐行解讀這個範例。先看程式碼如下:

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}
Code language: Arduino (arduino)

程式碼很簡單,功能就是輸出一行文字。

接下來由上到下,逐行解析每一段程式碼。

1. #include <stdio.h>

第一堂課我們簡單提到前置處理,這裡第一行程式碼就是前置處理指令。要怎麼判斷?關鍵就是 # 這個符號。

#:前置處理指令標記,交給前置處理器執行,是編譯程式的第一步。

include:匯入標頭檔關鍵字,作用是將指定檔案內的程式碼複製貼到目前的程式當中。

<stdio.h>:標準輸入輸出標頭檔(standard input output)。裡面封裝了畫面列印、鍵盤讀取等輸入輸出相關函式,下方使用的 printf 函式就定義在這個檔案內。

嚴格來說,前置處理並不屬於C語言本身的語法,C語言的前置處理並非C語言核心語法的一部分,而是編譯器在正式編譯前獨立執行的階段。它屬於完整編譯流程的一環,但不歸屬C語言本身的語意與語法體系。

簡單講,會先由獨立的前置處理程式做文字替換動作;以這行 #include <stdio.h> 為例,就是把 stdio.h 檔內所有程式碼複製到這一行的位置,直接替換掉這整句 #include <stdio.h>。假設 stdio.h 裡面只有文字 AAAAAAAAA

那麼實際送到編譯器處理前,程式碼會變成下面這樣:

 AAAAAAAAA

int main()
{
    printf("hello, world\n");
    return 0;
}
Code language: Arduino (arduino)

當然這只是假設標頭檔內容只有 AAAAAAAAA,實際檔案內容複雜許多。有興趣的同學可以自行打開這個標頭檔觀看。

這個標頭檔就存放在你的電腦裡,不同作業系統存放路徑不同:

Linux/Unix 系統:通常位於 /usr/include/stdio.h。

Windows (Visual Studio):位於 VC/include/stdio.h。

macOS (Xcode):位於 /Applications/Xcode.app/.../usr/include/stdio.h。

各位可以使用搜尋工具,查詢自己電腦上這個檔案的實際位置。

現在你應該對前置處理有基礎概念了吧?

如果少了這一行 #include <stdio.h>,編譯器無法辨識 printf,會直接拋出錯誤。各位可以試著刪除這行程式碼,再透過gcc執行編譯觀察結果。

刪除標頭檔後的程式

再次執行編譯就會出現錯誤訊息

2. int main()

main = C語言程式進入點函式

  1. 任何C語言程式執行時,作業系統都會自動從 main 函式開始執行,一份程式有且只能有一個 main 函式
  2. int:代表函式回傳值型別,全名 integer,也就是整數。
  3. ():代表這是函式,括號內可填入參數;空括號代表不接收任何參數。

這個 main 寫法也被後續多數程式語言沿用,它是程式唯一進入點。當你雙擊exe執行檔,或是在命令列輸入指令執行程式(例如輸入hello),作業系統就會自動呼叫這個 main 函式,由作業系統負責觸發執行。

開頭的 int 是函式的回傳型別,後續我們自訂函式時,每個函式都必須標註回傳型別,等到後續章節會詳細說明。

小括號()用來宣告函式能接收哪些型別的參數;這裡括號留白,代表此函式不接收參數。我們也可以寫成接收參數的版本,範例如下:

int main(int argc, char *argv[])Code language: CSS (css)

這樣撰寫代表函式會接收兩個參數,一個int型別、一個字串陣列,這部分會留到後續課程再詳細解釋。

main 函式的參數是由作業系統自動傳入,那這些參數從哪裡取得?

各位應該用過命令列工具,像是 ping 指令。舉例來說,執行 ping 12.36.4.xxx 測試連線,這裡 ping 對應 ping.exe 程式,後面的IP位址 12.36.4.xxx 就是傳入 ping.exe 的 main 函式參數。

同理我們的hello程式,如果在命令列輸入 hello abc,abc 就會做為參數傳入程式;main 後方小括號內的參數,就是用來接收這類由使用者輸入、作業系統轉交的內容。

總結先簡單記住:main 是程式唯一進入點、只能有一個,由作業系統自動呼叫,命令列輸入的參數也會透過作業系統交給 main。

3. { } 大括號

定義函式主體的邊界,{ 代表函式內容開始,} 代表函式內容結束,函式所有執行程式碼都要寫在兩個大括號中間。

4. printf("hello, world\n");

  • printf:全名 print format,格式化輸出函式,功能是在控制台畫面列印文字。
  • 雙引號 " ":用來包覆字串常數,引號內就是要輸出的文字內容。
  • \n:跳脫字元,換行符號,文字列印完後自動切到下一行。
  • ;:C語言陳述式結束標記,每一行可執行的程式陳述結尾都必須加上分號,遺漏會造成編譯錯誤。

函式名稱後面的f代表格式化輸出,後續章節會深入講解。現在先簡單理解:這行程式會把文字 hello, world\n 顯示在控制台,其中 \n 負責在文字輸出完成後自動換行。

5. return 0;

  • return:對 main 函式回傳一個整數,同時終止當前函式執行。為什麼一定要寫return?因為main開頭宣告回傳型別是int,函式內必須回傳一個整數。
  • 0:業界約定代表程式正常執行、無錯誤結束,用來告知作業系統程式執行狀態。
    • 回傳 0 = 程式執行成功、無異常
    • 回傳非0數字(例如 return 1;)= 程式執行發生異常、異常結束

現代C標準允許省略 main 函式最後的 return 0;,編譯器會自動補上,但新手建議依照規範完整寫出。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *