基本概念


  1. "hello, world!" 的啟示
    1. 「忠言逆耳利於行」 -- 與其執行程式時得到一個莫名其妙的 錯誤訊息, 不如讓 compiler 在編譯時多抱怨.
    2. 凡是我們呼叫 (invoke) 到的函數, 都要先宣告 (declare) 過!
    3. 宣告的目的在告訴編譯器這個函數 (例如 printf) 期望接到幾個參數, 每個參數的型別各是甚麼, 這樣編譯器才好檢查主程式呼叫的方式是否正確.
    4. printf 在 stdio.h 檔案中有宣告
  2. 電腦的長處: 機械化地處理大量的資料、 不厭其煩地重複類似的工作. 範例: 寫一個程式計算 1+2+3...+100. 提示:
    1. 使用到任何儲存空間也都需要先宣告, 例如以 int ... 告訴編譯器我們需要可以儲存整數的盒子.
    2. 本題需要用到很多儲存空間嗎? 想像你在一間空房間內, 只有一小張紙和一塊橡皮擦...
    3. 以迴圈處理重複的動作. 例如 for 迴圈.
    4. 主程式的參數列: void 表示不需要使用者輸入任何參數.
    5. printf 當中, 以 %d 表示要將後面的參數以十進位 (decimal) 方式印出.
  3. 骨架程式
    1. 自己用編輯器鍵入範例程式 skeleton.c
    2. Compile 之後以 "a.out 13 5" 執行.
    3. 所有的 C 程式都要有 main 這個函數, 它是整個程式的入口.
    4. argc 記錄命令列字串總共有多少個字串; argv[0] 存有你寫的程式名稱; argv[1], argv[2], ... 存有命令列上的參數.
    5. 用 atoi 將字串轉換成數字; aoti 宣告於 stdlib.h 中.
    6. 以 printf 印數字: %d 十進位, %x 十六進位, %2x 十六進位而且一定保留兩個字元的位置.
    7. 作業: 修改 skeleton.c, 從命令列讀入 3 個整數, 印出最大的那一個.
    8. 作業: 以此骨架程式研究各種 運算子的效果.
      1. % 及 / 作用在整數與實數上有何不同?
      2. ++k 和 k++ 有何不同?
      3. && 和 & 有何不同? || 和 | 有何不同?
    9. 作業: 印出 "f-f 乘法表", 並用以徒手計算 16 進位數的乘法作為驗証.
    10. 作業: 從命令列上讀入許多個整數, 求這些整數的和. 例如 "a.out 21 5 17" 應印出 "21 + 5 + 17 = 43". 你的程式能否處理負數?
  4. 除錯練習: 請以 gcd.c 練習使用你的編譯器所提供的除錯功能.
  5. 好的程式應該對使用者或系統所產生的各種錯誤狀況做出正確的反應; 最最起碼也應該常用 assert 確定你心裡的假設與事實吻合.
  6. 術語、專有名詞
    1. Identifier (識別字): 變數與函數的名稱, 如 i, j, main, argc, argv, printf, x0, y0, last_name, ... 如果把內建的識別字拿來當做自己的變數的名稱, 編譯或許會通過; 如果程式寫得很小心, 也可以執行. 避免自行定義以 _ 開頭的識別字.
    2. Reserved word (保留字): 長得像 identifier, 但是被 C 編譯器 保留下來, 具有特殊意義, 不可以當做變數與函數的名稱, 如 int, return, if, for, ...
    3. Literal: 就是那個已經明明白白寫出來, 不必再解釋的東西, 如 23, 14.9, 'A', "hello, world!", 0xf24c, ... ("literal" 英文原意: 按字面意義去理解, 不要再加以引申解釋; 例: "帥呆了", "熱昏了", "酷斃了")
    4. Type (型別): 例如 int, double, char, ...
    5. Operator (運算子): 例如 +, -, *, /, %, ++, ...
    6. Operand (運算元): 餵給 operator 吃的東西, 例如放在運算子左右的 literal 與變數名字
    7. Expression (運算式): 一大堆 operators 和 operands 湊在一起, 如 i+j, (line_no % 5) + 1, ...
    8. function (函數), subroutine (副程式), procedure (程序): 對 C 而言沒有什麼差別.
    9. function declaration (函數宣告) 的作用只是告訴編譯器說有人會提供某個函數給我們用 (只寫出函數的頭, 包含名稱, 參數個數及型別, 傳回值型別); function definition (函數定義) 的作用則是告訴編譯器如何計算出函數值 (包含函數的身體, 從左大括弧起到右大括弧為止).
    10. variable declaration (變數宣告) 的作用只是告訴編譯器說有人會提供某個變數的空間給我們用; variable definition (變數定義) 的作用則是真的向系統要一塊空間. 通常變數的宣告與定義一次完成.
    11. statement (敘述): 一句完整的 C 程式命令. 通常由分號結尾.
    12. syntax (語法) v.s. semantics (語意): 語法正確, 語意可疑 (syntactically correct, semantically dubious) 的中文例子: "海水是藍的, 天空是鹹的" 語法檢查是機械化的動作, 編譯時就可以做; 語意的錯誤往往要等到聯結或執行時才看得出來.