《C程序設計語言》總結一

《C程序設計語言》總結一

這段時間正在重新學習C語言,原來就聽老師說過K&R,就選擇了K&R的《C程序設計語言》;讀了一些也記錄一下瑣碎的東西(個人習慣)。有錯誤的地方希望大家可以指正。

1. C語言除了靜態定義和棧自行分配以外沒有定義其他的存儲分配方式,沒有堆或者垃圾回收(The language does not define any storage allocation facility other than static definition and the stack discipline provided by the local variables of functions;there is no heap or garbage collection)
2. C語言中所有的變量都必須在用之前聲明,通常在函數開始處,在所有可執行語句之前。
3. 儘管C編譯器不關心一個程序的編程風格是什麼樣的,適當的縮進和空格會使程序容易讀和理解。每行只寫一條語句,在操作符兩邊用空格來表明分類。
4. 如果一個算術運算符有整型操作數,會進行整型操作。如果一個算術運算符有一個浮點操作數和一個整型操作數,那麼整型操作數會在操作進行之前轉換成浮點數。
5. 在C語言中,任何賦值語句都是一個表達式並且有一個值,整個表達式的值是在賦值完成以後賦值號左邊的變量的值。
6. 用兩個單引號‘’括起來的字符代表一個整型值,這個整型值與這個字符在機器字符集(machine’s character set)中對應的數值相同,這就是字符常量,其實就是比較小的整數的另一種寫法。
7. 用&&和||連接的表達式從左到右求值,並保證在在求值過程中,只要能判斷最終結果的真假,求值就會終止。
8. 數組下標可以是任何整型表達式,包括整型變量和整型常量。
9. 根據定義,char只是小一些的整數,所以char類型的變量和常量在算術表達式和int是同樣的。
10. 不帶有表達式的return語句把控制權交還給調用者,但是沒有返回值,就像是程序運行到終止的右括號。
11. 一般常用return 0表示正常終止,非零值表示不正常或錯誤終止的情況。
12. C語言中所有函數參數都是通過值傳遞。就是說被調用的函數的參數的值是通過臨時變量的方式得到的,而不是主調函數中的原本的變量。
13. C語言中被調用函數不能直接更改主調函數中的值,它只能改變它私有的、臨時的拷貝版本。相當於在函數調用中,被調函數會重新在函數體中定義參數變量,它們的值就是主調函數調用被調函數時所用的值。
14. 當數組名被作爲參數時,傳遞的是數組的起始地址,並沒有數組元素的拷貝。
15. 局部變量在函數被調用時存在,函數執行完畢退出時消失。
16. 一個外部變量必須定義在所有函數之外,而且在所有的源文件中只能定義一次,在定義時會分配存儲空間。
17. 通常把變量和函數的extern聲明放到一個單獨的文件中(習慣上稱頭文件),通過#include在每個源文件的最前面包括進來。
18. “定義”指的是變量被創建和分配空間,“聲明”指的是說明變量的性質,但並不分配存儲空間。
19. 定義變量的時候不要用下劃線開頭!
20. 傳統C語言用法中變量名用小寫字母,符號常量全部用大寫字母。
21. 不帶限定符的char類型對象是有符號的還是無符號的取決於具體的機器,但是可打印的字符都是正數。
22. 整型常量前面帶0代表八進制,前面帶0x或0X代表十六進制。
23. 一個字符常量的值是它在機器字符集中對應的值。
24. 字符常量可以像其他整型一樣參與數值運算,儘管常常用來和其他的字符作比較。
25. ‘\0’經常用來代替0來強調一個表達式的字符特性,其實它實際的值就是0。
26. 常量表達式是隻有常量的表達式,這種表達式在編譯階段就可以求值而不是在運行時求值。
27. 一個字符串的內部表示在末尾處有’\0’(空字符),所以一個字符串實際物理上所需要的存儲空間比寫在雙引號之間的多一個。
28. 枚舉類型中第一個的值是0,第二個是1,然後依次下去,除非有明確的賦值。
29. 儘管可以聲明枚舉類型的變量,但是編譯器並不檢查這種類型變量中存儲的值是否爲該枚舉的有效值。
30. 外部變量和靜態變量在默認情況下被初始成0。
31. const可以用於所有變量聲明中,表明它的值不能被改變。
32. const也可以用於數組參數中,表明這個函數不能改變這個數組。
33. %不能用於float和double。
34. 算數運算符>關係運算符>邏輯運算符
35. 總體上,唯一的自動轉換是那些“narrower”操作數轉換成“wider”操作數,這樣轉換不會丟失信息(比如int轉換爲char就會丟失前面三個字節的信息)。會丟失信息的轉換可能會有警告但完全合法。
36. 在char類型到整型的轉換中,因爲沒有具體定義char類型是有符號的還是無符號的,那麼這種轉換會產生一個負數嗎。答案不確定。(不過我覺得各種編譯器應該已經確定了這種情況)
37. 所以爲了便於可移植,當非字符型的數據要存儲到char類型變量中時,說明是有符號還是無符號。
38. 在一個二元運算符中,如果操作數不同類型,那麼在運算進行之前,低類型會轉換到高類型。
39. 注意,float並不會自動轉換到double。
40. 賦值時,右邊的值會自動轉換成左邊的類型,左邊的類型就是結果的類型。
41. 轉換規則:有long double轉到long double;否則有double轉double;否則有float轉float;否則把char和short轉爲int;然後如果有long,把其他轉爲long。
42. double轉爲float時是四捨五入還是截取取決於機器。
43. 注意,強制類型轉換運算符只是產生一個值爲n的合適的類型,n本身並沒有改變。
44. 如果有函數原型聲明,當函數調用時,自動強制類型轉換爲參數類型。
45. n++先使用n後對n進行+1,++n先對n進行+1,再使用n的值。
46. 右移一個無符號數空位填0,右移一個有符號數在某些機器上空位補符號位(算術右移),在另一些機器上空位補0(邏輯右移)。
47. 用unsigned修飾保證右移時空位補0。
48. 所有表達式中,賦值表達式的值和類型是賦值以後左操作數的值和類型。
49. 條件表達式expr1 ? expr2 : expr3,實際上也是一個表達式,可以出現在其他任何表達式可以出現的地方。如果expr2和expr3有不同的類型(比如float和int),那麼這個表達式就是float類型不管條件判斷是什麼樣。
50. C語言沒有明確定義一個操作符的操作數的求值順序(除了&&,||,?:,’,’這幾個操作符)。例如x = f() + g();f和g誰先求不能確定下來。同樣的,函數參數中的求值順序也是不確定的
51. 函數調用,嵌套賦值語句,增量和減量操作會產生副作用,某些變量的改變可能是因爲一個表達式的求值產生的副作用。
52. 分隔函數參數,變量聲明等等的逗號不是逗號操作符,不保證從左到右求值。
53. break語句導致最內層的循環或switch語句中立刻跳出。
54. continue語句使for、while、或者do循環的下一次迭代立即開始。在while和do中,表示判斷部分立即執行,在for語句中,進行增量步驟執行;在for循環中的switch中的continue使for循環開始下一次迭代。
55. 如果函數有參數就聲明,沒有參數就用void。
56. 任何函數都可以通過變量名引用外部變量,只要以某種方式聲明。
57. 外部變量作用域是從它聲明的地方開始到被編譯文件的末尾。
58. 外部變量的初始化在值在定義時執行。
59. 到某種程度的程序,只需要一個頭文件包含所有的東西。再大一點的或可以考慮更多的頭文件。
60. static靜態修飾符:①修飾外部變量或者函數的時候,表明這個變量或者函數的作用域只有在它們定義的這個文件當中;②修飾內部變量的時候,爲一個函數提供私有的永久的存儲空間。(不再是當函數被調用時存在,執行完畢退出後消失)
61. 在沒有明確的初始化的情況下,外部變量和靜態變量保證被初始化爲0。自動變量和寄存器變量沒有定義初始值。對於外部變量和靜態變量,必須用常量表達式初始化。
62. 通常用明確的賦值,在聲明時初始化不便於閱讀程序。
63. 在初始數組時,提供的值比數組元素個數少的時候,剩下的自動初始爲0。不能一次將一個初始化表達式指定給多個數組元素,也不能跳過前面的數組元素而直接初始化後面的數組元素。
64. #include中用”“包含,就先從程序所在的文件查找頭文件,如果沒有找到,再按定義的路徑查找;用<>包含就按照定義的路徑查找。
65. 可以定義帶參數的宏替換,那麼在不同的宏調用中替換的文本也就不同。例如#define max(A, B) ((A) > (B) ? (A) : (B))看起來像是函數調用,但是用max會擴展成內置代碼。
66. 上面的表達式其實被求值了兩次,如果包含有副作用的表達式,會出現錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章