1. 程式人生 > >《C語言程式設計:現代方法(第2版)(K.N.King 著)》學習筆記六:C語言基本概念(5)

《C語言程式設計:現代方法(第2版)(K.N.King 著)》學習筆記六:C語言基本概念(5)

問與答

  1. GCC 最初是 GNU C Compiler 的簡稱。現在指 GNU Compiler Collection,這是因為最新版本的 GCC 能夠編譯用 Ada、C、C++、Fortran、Java 和 Objective-C 等多種語言編寫的程式。
  2. GCC 有多個命令列選項來控制程式檢查的徹底程度。使用這些選項可以幫助我們有效地找出程式中潛在的故障區域。下面是一些比較常用的選項:
  • -Wall:使編譯器在檢測到可能的錯誤時生成警告訊息。(-W 後面可以加上具體的警告程式碼,-Wall 表示“所有的 -W 選項”。)為了獲得最好的效果,該選項應與 -O 選項結合使用。
  • -W:除了 -Wall 生成的警告訊息外,還需要針對具體情況的額外警告訊息。
  • -pedantic:根據C標準的要求生成警告訊息。這樣可以避免在程式中使用非標準特性。
  • -ansi:禁用 GCC 的非標準C特性,並啟用一些不太常用的標準特性。
  • -std=c89-std=c99:指明使用哪個版本的C編譯器來檢查程式。
  1. 這些選項常常可以結合使用:
% gcc -O -Wall -W -pedantic -ansi -std=c99 -o pun pun.c
  1. 當出現在 main 函式中時,return 0;exit(0); 這兩種語句是完全等價的:二者都終止程式執行,並且向作業系統返回 0 值。
  2. 在 main 函式的末尾,return 語句不是必需的。如果沒有 return 語句,程式一樣會終止。在 C89 中,返回給作業系統的值是未定義的。在 C99 中,如果 main 函式宣告中的返回型別是 int,程式會向作業系統返回 0;否則程式會返回一個不確定的值。
  3. 一些早期的編譯器會刪除每條註釋中的所有字元,使得語句 a/**/b = 0; 可能被編譯器理解成 ab = 0;。然而,依據C標準,編譯器必須用一個空格字元替換掉每條註釋語句,因此上面提到的技巧並不可行。我們實際上會得到這樣的語句:a b = 0;
  4. 如何發現程式有沒有未終止的註釋?如果運氣好的話,程式將無法通過編譯,因為這樣的註釋會導致程式非法。如果程式可以通過編譯,也有幾種方法可以用。通過用偵錯程式逐行地執行程式,就會發現是否有些行被跳過了。某些整合開發環境會使用特別的顏色把註釋和其他程式碼區分開來。如果你使用的是這樣的開發環境,就會很容易發現未終止的註釋,因為誤把程式文字包含到註釋中會導致顏色不同。此外,諸如 lint 之類的程式也可以提供幫助。
  5. 傳統風格的註釋(/* ... */)不允許巢狀。例如,下面的程式碼就是不合法的:
/*
    /***  WRONG ***/
*/
  1. 上面的程式碼中第 2 行的符號 */ 會和第 1 行的 /* 相匹配,所以編譯器將會把第 3 行的 */ 標記為一個錯誤。
  2. C語言禁止註釋巢狀有些時候也是個問題。假設我們編寫了一個很長的程式,其中包含了許多短小的註釋。為了臨時遮蔽程式的某些部分(比如在測試過程中),我們首先會想到用 /**/ “註釋掉”相應的程式行。但是,如果這些程式碼行中包含有傳統風格的註釋,這種方法就行不通了。不過,C99 註釋(以 // 開始的註釋)可以巢狀在傳統風格的註釋中,這是這類註釋的另一個優勢。在今後的學習中我們將看到,可以用一種更好的方法來遮蔽部分程式。
  3. float 是 floating-point 的縮寫形式,它是一種儲存數的方法,而這些數中的小數點是“浮動的”。float 型別的值通常分成兩部分儲存:小數部分(或者稱為尾數部分)和指數部分。例如,12.0 這個數可以以 1.5 × 232^{3} 的形式儲存,其中 1.5 是小數部分,而 3 是指數部分。有些程式語言把這種型別稱為 real 型別而不是 float 型別。
  4. 包含小數點但卻不以 f 結尾的常量是 double(double precision 的縮寫)型的。double 型的值比 float 型的值儲存得更精確,並且可以儲存比 float 型更大的值,因此在給 float 型變數賦值時需要加上字母 f。如果不加 f,編譯器可能會生成一條警告訊息,告訴你儲存到 float 型變數中的數可能超出了該變數的取值範圍。
  5. C89標準聲稱識別符號可以任意長,但卻只要求編譯器記住前 31 個字元(C99中是 63 個字元)。因此,如果兩個名字的前 31 個字元都相同,編譯器可能會無法區別它們。更復雜的情況是,C標準對於具有外部連結的識別符號有特殊的規定,而大多數函式名都屬於這類識別符號。因為連結器必須能識別這些名字,而一些早期的連結器又只能處理短名字,所以在 C89 中只有前 6 個字元才是有效的。此外,還不區分字母的大小寫。(C99中,前 31 個字元有效,且字母區分大小寫。)大多數編譯器和連結器都比標準所要求的寬鬆,所以實際使用中這些規則都不是問題。不要擔心識別符號太長,還是注意不要把它們定義得太短吧。
  6. 縮排時應該使用多少空格?如果預留的空間過少,會不易察覺到縮排;如果預留的太多,則可能會導致行寬超出螢幕(或頁面)的寬度。許多C程式設計師採用 8 個空格(即一個製表鍵)來縮排巢狀語句,這可能太多了。研究表明,縮排 3 個空格是最合適的,但許多程式設計師不太習慣於非 2 的冪次。

練習題

練習題 1 練習題 2 [我的答案]

  1. 答:有警告資訊。需要在 main 函式的末尾加上語句 return 0;
  2. (a)指令:#include <stdio.h>;語句:printf("Parkinson's Law:\nWork expands so as to ");printf("fill the time\n");printf("available for its completion.\n");return 0;。(b)程式的輸出如下:

Parkinson’s Law: Work expands so as to fill the time available for its completion.

  1. dweight.c 按題意縮寫後如下:
#include <stdio.h>
int main(void)
{
    int height = 8, length = 12, width = 10, volume;

    volume = height * length * width;

    printf("Dimensions: %dx%dx%d\n", length, width, height);
    printf("Volume (cubic inches): %d\n", volume);
    printf("Dimensional weight (pounds): %d\n", (volume + 165) / 166);

    return 0;
}
  1. 答:沒有規律。
  2. (a)不合法。(b)合法。(c)合法。(d)合法。
  3. 答:因為這讓讀者難以辨認出下劃線的數量。
  4. (a)是。(b)不是。(c)不是。(d)不是。(e)是。
  5. 答:一共有 14 個記號。
  6. 答:按題意修改後的語句為 answer = (3 * q - p * p) / 3;
  7. 答: 第 4 行中 int 與 main 之間的空格、第 6 行中 int 與 height… 之間的空格和第 20 行中 return 和 0 之間的空格是必不可少的。(行序數參照 《C語言程式設計:現代方法(第2版)(K.N.King 著)》學習筆記三:C語言基本概念(2) 中的 dweight.c 程式)