1. 程式人生 > >C Primer Plus(二)

C Primer Plus(二)

重讀C Primer Plus ,查漏補缺

  重讀C Primer Plus,記錄遺漏的、未掌握的、不清楚的知識點

 

分支和跳轉

  1、ctype.h標頭檔案裡包含了一些列用於字元判斷的函式,包括判斷數字、大小寫字母,控制字元,可列印字元等一些列函式以及轉換字母大小寫的字元對映函式。

  2、C99標準要求編譯器支援至少127層if-else巢狀。

  3、包含iso646.h標頭檔案,可以使用and、or、not代替 &&、||、!,這是為了適應世界各地的鍵碟符號。

 

字元輸入/輸出和輸入確認

4、 緩衝區分為完全緩衝和行緩衝,完全緩衝在緩衝區滿時清空,行緩衝在遇到換行時清空,例如檔案輸入(完全)和標準輸入(行),緩衝區大小取決於作業系統,512和4096位元組是常見的值。

5、在多數Unix環境下,用[Ctrl+D]可以模擬產生一個檔案尾訊號,用以通知讀取標準輸入的程式已讀取完,可能這也和互動模式下Python用這個快捷鍵關閉互動模式有關。

6、Unix下的重定向運算子,輸入重定向<,輸出重定向>,兩個運算子可以組合使用。他們只可以連線可執行檔案和資料檔案,同類型不能連線,同時輸入和輸出不能重定向到一個以上的檔案。

7、同時Unix還具有追加資料運算子>>,管道運算子 |,具體用法就要參照Unix相關書籍了,這並不是C的一部分。

 

函式

8、注意設定遞迴的結束條件,以及指標的用法,沒有其餘需要注意的內容。

 

陣列和指標 

  9、C99標準支援初始化特定專案,如:

1 int arr[10] = {1,2,3,[5]=31}

未被初始化的專案都將被置為0。

10、 對於一個二維(多維)陣列arr[n][m]而言,arr+1和arr[0]+1是不同的。

11、對於二維陣列來說,arr時地址的地 址,要取兩次值才可以得到通常的數值。

1 這裡添一句題外話,在《C Primer Plus》第五版中,P267程式清單10.15的程式碼和程式碼輸出
2 結果不一致,兩個二維陣列的下標寫反了。
3 在輸出中:
4 zippo[1][2]  應寫為  zippo[2][1]
5 *(*(zippo+1)+2)   應寫為   *(*(zippo+2)+1) 

12、int (*arr)[2] 表示指向一個包含兩個int的陣列的指標;

int *arr[2] 表示包含兩個int型別指標的陣列,出現這個差別的原因在於運算子的結合性。

arr[m][n] 等價於 *(*(arr+m)+n)

13、對於N維陣列,int arr[][10][20][30] 等價於 int (*ar) [10][20][30]

第一個方括號中可以不寫,因為它將被認為是一個數組的指標,後面的數字則確定了具體的資料型別,必須填寫。

14、C99標準支援變長陣列,指維數可以用變數宣告的陣列,並不是維數可變,在函式引數中省略變數名時,應用星號代替維數,int sum(int, int, int [*][*]);

15、C99標準支援複合文字,例如(int [2])= {10, 20},因為是匿名變數,所以必須是宣告時立刻使用,或者用指標儲存其地址。目前還沒用過這個特性。

 

字串和字串函式

16、用陣列的方法初始化一個字串時,陣列尾部未被使用的記憶體全部被初始化為\0,並不是只有字串結尾處被賦值\0。

17、char *m3 = "hello" 和 char m3[] = "hello" 在宣告上作用幾乎相同。不同的是,陣列名是常量,無法修改其值,但指標是可以的。

1 這裡又發現一處本書的錯誤:
2 P285中間偏下的位置  const char *m3[] = "....省略....." 應該為
3                    const char *m3 = "....省略....."

18、對於char arr[m][n] 和 char* arr[] 來說,前者是一個字串陣列,也是一個矩形陣列,而後者是一個字串型別的指標陣列,它其實也是矩形的,但其中儲存的是地址,而字串儲存在程式用來儲存常量的那部分,所以沒有被浪費掉的空間,但是這些串是不能被修改的。

19、fgets函式相比gets更加安全,可以指定讀入的資料長度,遇到換行符也同樣讀入,同時可以指定從哪一個檔案讀入,標準輸入UNIX下可指定為stdin。

20、對於命令列中的引數,作業系統預設以空格劃分一個個字串,UNIX也允許使用引號把多個單詞集中在一個引數裡,例:

1 repeat "I am hungry" now

21、字串轉換為整數,常用atoi,還有atof,atol。複雜的有,strtol,strtoul,strtod,可以找出第一個非數字字元,並且可以轉換相應進位制,不常用。

 

儲存類、連結和記憶體管理

22、對於具有檔案作用域的變數(即通常所說的全域性變數),static表明其連結型別維內部連結,只有這個檔案中的函式可以訪問這個變數。

23、五種儲存類:

儲存類 時期 作用域 連結屬性 宣告方式
自動 自動 程式碼塊 程式碼塊內
暫存器 自動 程式碼塊 程式碼塊內,使用關鍵字register
具有外部連結的靜態 靜態 檔案 外部 所有函式之外
具有內部連結的靜態 靜態 檔案 內部 所有函式之外,使用關鍵字static
空連結的靜態 靜態 程式碼塊 程式碼塊內,使用關鍵字static

 

24、對於下列程式碼:

1 double *ptd = (double*) malloc (30 * sizeof(double))

  在C中,型別指派(double*)是可選的,但在C++中必須有,因此使用型別指派可使程式由C移植到C++更容易。

25、分配記憶體時,calloc函式接收兩個引數,並且會將申請到的塊記憶體全部置為0,但有些硬體系統浮點值並不全部用0表示。

26、一個位於*前的const使得指向的資料成為常量,位於*後的const使得指標成為常量。

27、restrict只能用來修飾指標,且這個指標指向的資料塊由該指標初始且唯一訪問,編譯器會將根據這一點,對多條涉及這個指標的運算進行優化。

28、在C99標準下,有一些舊關鍵字可以出現在新的位置。

1 void fun(int a1[const], int a2[restrict], int n)
2 void fun(double ar[static 20])