C 語言與系統程式

目前,在許多資訊與電子相關科系中,都是以 C 語言做為第一個程式語言,但是,C 語言絕對不是簡單的語言。相反的,C語言當中有很多陷阱,會令初學者百思不得其解。即便是C語言的專家,在使用這個語言時,都要敬畏三分。因為,C語言是以效率為首要考量,而非學習的容易程度。雖然,筆者已經學過 Pascal, C, VB, Foxpro, Java, C#, LISP, Prolog, Ruby, Python, ASP 等語言,但是,C語言仍是我所學習過的語言當中最難學,也是最容易出錯的一個語言。

舉例而言,C語言中的指標經常會造成錯誤百出的狀況,但由於指標是C語言強而有力的武器,在低階輸出入、效能表現、與靈活度上都有很強的用途,因此,指標可以說是一把鋒利的雙面刃,若不砍死敵人就會砍傷自己。

C語言中的指標

在C語言當中,宣告指標的情況很常見,C語言中的各種型態都可以加上星號 (*) 後就成為指標型態,而且,指標可以指向任何的記憶體區塊,舉例而言,下列程式可以將 'a' 字元塞入到記憶體位址 100 當中,這種方式常被用來存取記譯體映射輸出入的暫存器。

char *ptr=(char*) 100;
*ptr = 'a'

函數指標是C語言中相當常用到的功能之一,但是這個主題卻有相當的難度。利用函式指標可以進行反向呼叫 (Call Back Function),舉例而言,在標準函式庫中的 qsort 函數,就使用了 int (*compare)(const void *, const void *) 這樣一個函數指標。

為了效率的考量,C語言的函式庫通常採用靜態的配置方式,盡可能避免動態配置記憶體,因此像 strcpy(), sscanf() 等函數都不會動態配置記憶體,這樣可以讓函數使用者自行決定是否要自行配置方式。但是,當使用者決定以靜態的方式宣告陣列或字串大小,而不採用動態配置時,通常會很難決定陣列或字串所需的空間大小。因此,撰寫 C 語言的程式設計人員對記憶體的掌握度較高,但是也相對必須花費許多程式碼在記憶體管理上。

C語言由於設計上非常注重效率問題,而且與組合語言之間的連接相當良好,因此,很早就成為了系統程式的主流語言。但是,由於C語言的歷史淵遠流長,而且早已被廣泛使用在各個作業系統的撰寫上,這也使得C語言的函式庫相當的不統一。

雖然,ISO組織定義了 C 語言的標準函式庫,但是,這些函式庫有時會不足以應付許多實務上的應用,因此,各家廠商經常會自行發展其C語言函式庫,舉例而言,微軟平台的C語言函式庫與GNU的C語言函式庫就相當不同。更嚴重的是,由於各家作業系統幾乎都是以 C/C++所開發的,因此,各自擁有不同的系統函式庫,這對C語言的開發人員而言,造成了一些困擾,因為,要學習作業系統上的程式設計,就必須分別學習各個作業系統不同的函式庫。

ISO組織定義的C語言函式庫,是以函數為主的定義方式,但是,卻缺乏標準的資料結構,像是 HashTable, Binary Tree 等,這使得C語言的開發者常常被迫要重寫這些結構的相關函數,還好,在開放原始碼領域,GNU已經為我們製作了一些廣泛被使用的函式庫,稱為 GNU C library (glibc) 。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License