C 程式設計/C 的特點
外觀
< C 程式設計
C 是一種高效、簡約的語言,它有一些程式設計師必須注意的特殊之處。為了解決這些問題,有時一個好的解決方案是將另一種語言與 C 結合使用,以獲得額外的靈活性和功能,例如 Emacs-LISP 和 C 的組合用於 Emacs。有時可以透過使用保證功能和安全的特殊結構來解決它們,但代價是速度變慢和複雜度增加。然而,大多數情況下,透過實踐,C 程式設計師不會遇到這裡提到的問題,並且更喜歡使用一種與通用馮·諾依曼硬體架構緊密匹配的語言。
以下是 ANSI C 中的一些特點(有時也是它的優勢),一些小,一些大
- 陣列和指標之間缺乏區別
- 最早的 C(大約 1973 年)根本沒有陣列;現代實現是記憶體中連續的區域,使用指標算術進行訪問(注意:宣告的陣列不能像指標一樣賦值),這避免了使用固定大小宣告陣列的必要性。但是,這種能力在使用不當的情況下會導致緩衝區溢位錯誤。
- 陣列不儲存它們的長度
- 上述特性的一個後果。這意味著程式可能需要在訪問陣列之前顯式地執行邊界檢查。除非函式被傳遞一個固定大小的陣列,否則它無法發現它被傳遞的陣列的長度:因此,函式必須被傳遞長度,也許作為單獨的變數傳遞給函式或在結構中傳遞。因此,大多數實現不提供自動陣列邊界檢查,而手動邊界檢查容易出錯。
- 如果 C(或 C++)程式試圖訪問超出實際分配記憶體的陣列元素,則會發生緩衝區溢位,通常會使程式崩潰。緩衝區溢位錯誤也是常見的安全漏洞。許多其他計算機語言提供自動邊界檢查,因此它們幾乎不受此類錯誤的影響。[1][2][3][4][5]
- 可變長度陣列
- VLA ‒ 可變長度陣列 ‒ 只能用於函式引數和自動變數。VLA 不能在結構體內部使用(除非作為結構體的最後一個專案)。不可能定義一個對應於標準 Forth 字典定義(它有兩個可變長度部分)的結構,除非作為
char的未區分陣列。
- 內建的 2D 或 3D 陣列的大小不受限制
- 此功能已從 C99 規範開始新增,用於可變長度陣列,儘管許多 C 編譯器仍然不支援它。如果沒有 VLA,函式無法接受任意大小的 2D 或 3D 陣列。特別是,不可能定義一個接受
int a[5][4][3];在一次呼叫中,並在以後呼叫中接受int b[10][10][10];。而不是使用內建的 2D 或 3D 陣列資料型別,C 程式設計師使用其他資料型別來儲存(數學)任意大小的 2D 或 3D 陣列(多維陣列) - 請參見 C 程式設計/常見做法#動態多維陣列 瞭解詳細資訊。
- 沒有正式的字串資料型別
- 字串是字元陣列(缺乏任何抽象),並繼承了它們的所有約束(結構可以在一定程度上提供抽象)。
- 型別安全性較弱
- C 的型別安全性不是很高。記憶體管理函式在無型別指標上操作,沒有內建的執行時型別強制,並且可以透過指標和強制轉換來繞過型別系統。此外,typedef 不會建立新型別,而只是建立別名,因此它僅用於程式碼可讀性。但是,可以使用單成員結構來強制型別安全性。
- 沒有垃圾回收
- 作為一種旨在最小化開銷的低階語言,C 僅提供手動記憶體管理,這可能導致簡單的記憶體洩漏不受控制地繼續。
- 區域性變數在宣告時未初始化
- 區域性變數(但不是全域性變數)必須手動初始化;在此之前,它們包含宣告時記憶體中的任何內容。這並不罕見,但 C 標準並不禁止訪問未初始化的變數(這是)。
- 笨拙的函式指標語法
- 函式指標採用
[返回值型別] [名稱]([引數 1 型別])([引數 2 型別])的形式,使得它們難以使用。typedef 可以緩解這種繁重的語法。例如,typedef int fn(int i);。有關更多詳細資訊,請參見 C 程式設計/指標和陣列#指向函式的指標。
- 沒有反射
- C 程式在執行時無法將字串評估為源 C 程式碼語句。
- 巢狀函式不是標準
- 但是,許多 C 編譯器確實支援巢狀函式,包括 GNU C。[6]
- 沒有正式的異常處理
- 一些標準函式返回特殊值,必須手動處理。例如,
malloc()在失敗時返回 null。例如,必須將getchar()的返回值儲存在int中(而不是預期的那樣,儲存在char中),以便可靠地檢測檔案結束 - 請參見 EOF 陷阱。不包含適當錯誤處理的程式在大多數情況下可能執行良好,但在出現異常情況時可能會崩潰或出現其他故障。POSIX 系統通常使用signal()來處理某些型別的異常。(有關詳細資訊,請參見 C 程式設計/錯誤處理#訊號)。一些程式使用setjmp()、longjmp()或goto來手動處理某些型別的異常。(有關詳細資訊,請參見 C 程式設計/控制#最後一點:goto 和 C 程式設計/協程)。
- 沒有匿名函式定義
- ↑ http://projects.webappsec.org/Buffer-Overflow
- ↑ http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/buffer-overflow.html
- ↑ http://searchsecurity.techtarget.com/news/article/0,289142,sid14_gci860185,00.html
- ↑ http://www.owasp.org/index.php/Buffer_Overflows
- ↑ http://cyclone.thelanguage.org/wiki/Why%20Cyclone
- ↑ "GNU 手冊":"C 語言擴充套件:巢狀函式" [1]