從零開始學C語言
@閬苑祁寒
更新時間:2019-12-31
更新說明:此版本是最終版本。初始版本有關helloworld的內容調到了附錄部分。
pdf版本下載鏈接:
寫在前面:本文從一個初學者的角度,給出了對C語言的簡單理解。最近一次更新調整了之前的敘述方式。
目錄 |
|
Part1 |
從Hello World講起 |
Part2 |
知識結構梳理 |
Part3 |
一路走來的習題 |
Part4 |
實踐心得和疑難釋義 |
Part5 |
結束語 |
Part6 |
附錄 |
如有謬誤,敬請指出!
Part1 從Hello World講起
“C語言是一門計算機語言。”這表明:
(1)C語言是源於計算機的,通過C語言,可以接觸到計算機的某些工作原理。
(2)C語言是一門語言,既有和漢語和英語等語言相似的特性,也有語言所必須的語法結構。
(3)C語言是計算機語言,可唯一解釋性使得C語言有別於其他語言,反之,只要掌握了每一個語句的原理,很容易學好計算機語言。
要知道,想要學習好每一門學科,都必須了解其歷史,這也是歷史這門學科的主要價值。第一台計算機是美國賓夕法尼亞大學設計的用於彈道計算的ENIAC(英耐克),而與之密切的網絡則是為了彌補單一通訊方式的不足而被發明。可見,計算機和網絡都是隨戰爭誕生的,以及運籌學(優化算法的理論基礎)也是在二戰期間應運而生。因此,認為戰爭催化科技發展這句話毫不為過。
簡單了解ENIAC后,認識到其架構是具有時代局限性的,其程序和數據存儲是分開的,數據通過類似於電話接線局的接線方式來連接對應的程序。這是相當麻煩的,以至於從事曼哈頓計划的馮·諾依曼,改進了計算機的架構,將程序和數據放在一起,這也是馮·諾依曼被公認為計算機之父的原因。相反,現代電話都是程控接線,這表明技術的發展也永遠並不是單一領域的。
但是,這樣的簡化並不能適應大規模的運算。眾所周知,計算機數據和程序的存儲方式是二進制代碼,用1和0分別代表數字電路中的開和關,也即布爾代數中真(true)和假(false),一個二進制位稱為1 bit(比特),通常將8個二進制位稱為1 Byte(字節),在內存作為一個存儲空間。根據數理邏輯運算定義加和乘,就完成了傳統計算機體系的構建。
必須指出,我們公認的計算機編碼表ASCII表(American Standard Code for Information Interchange)就恰好有128=28個特殊字符(后被擴充到256個特殊字符),依次從0編號到127,對應1字節長度的二進制數字的十進制大小。
盡管將計算機架構中的數據存儲和程序放在一起,已經大大提高了計算機的效率。但對於程序本身而言,常常會出現一行固定指令被重復使用多次的情形。因此考慮將其提煉為機器語言(匯編語言),進而再一次提高了計算機的效率。進一步,將重復出現的機器語言再一次提煉,就得到了高級語言。
第一門高級語言C語言,具有划時代的意義,它連接了計算機組成(硬件)和計算機程序(軟件),這對於入門計算機學科是極好的。
不可否認,C語言並非十全十美。一方面,面向過程的靈活性(指針)常常會因為小小的錯誤而使整個程序乃至計算機崩潰(早期計算機內存並未設置程序與操作系統,以及不同程序之間的界限)。另一方面,盡管在函數和宏中初步體現了大規模程序開發的模塊化思想和封裝思想,但是例如C語言的函數不可互相嵌套等缺陷使得靈活性下降。除此之外,作為語言本身先於語法而出現的特性,決定了基於C語言的計算機語言的語法結構,在發展中必然是逐漸完善的。C語言一些看似不符合常理的語句,它們的出現就好解釋了。
局部來說,針對不同的目的,新出現的計算機語言在C語言的基礎上進行各自的改良。但從總體來說,計算機語言逐漸從面向過程到面向對象。程序的封裝,使得計算機程序員只需要查閱參考手冊相關包的使用說明,如無必要,不再去關注內部封裝的算法本身,這也是作為工程學科的一個重要特點。這些后續發展而來的語言也就因此被稱為面向對象的語言。
最后,包括C語言在內的諸多計算機語言,第一課與其說是認識計算機語言,不如說是認識最基本的語句Hello World里的所包含的全部信息及相關附錄!在此之前,你的手頭應該擁有一本C語言的教材,下面將一本講得非常明晰的教材推薦給大家:
《C語言程序設計教程》·姜恆遠·高等教育出版社
以下便是C語言的Hollow world程序(不止一種寫法,但它是最為經典的):
#include < stdio.h> int main(void) { printf("Hello, world! /n"); return 0; } |
最初拿到這個程序時,除了幾個類似於英文單詞的記號,其余的內容,就像初學一門新的課程一樣,其實大腦是一片空白的。也許好奇心驅使你稍稍改動這個程序,但更多的還是受改動范圍的局限和因為報錯而沮喪罷了。
下面對這個最基本的程序涉及到的基本語法列出如下:
☆ #include<stdio.h> 將標准輸入輸出的頭文件,在編譯時加載到源代碼的頭部。
☆ int main(void) 函數頭的聲明形式,聲明了一個名為main的函數,返回值類型是int類型,形式參數是void空類型。需要指出,main函數是C語言的主函數,有且僅有一個。一方面,編譯過程總是從主函數開始,再根據調用關系讀取其他的函數;另一方面,同名的函數會造成編譯沖突。
☆ {} 表示復合語句,常用在循環結構和函數體中,如果沒有花括號,C語言默認只逐級向下讀取一行,其余內容作為花括號(如果有)中的最大層級解釋。需要注意,C語言不像Python,會受到縮進的影響,反過來,有一個標准的編程規范,對於C語言的學習相當重要。
☆ printf("Hello, world! /n"); 調用了頭文件中的printf函數,輸出字符串常量,’\n’作為轉義字符表示換行。
☆ return 0; 函數返回值,相當於右花括號的作用,用於結束對應類型的函數。事實上,int類型的主函數有無返回值,對於編譯成功與否沒有影響。嚴格來說,對應數據類型的函數,必須要有對應數據類型的返回值。在初學時需要注意,返回值並不是輸出在屏幕上的值,而是函數本身有了一個值,也就是如果在另一個函數(主調函數)中調用這個函數(被調函數),這個函數的返回值可以賦給一個變量或者輸出。
紅色字體的部分可以參考“函數”和“結構化程序設計”章節的內容,高亮字體的部分可以參考“數據結構”章節的內容,紫色字體的部分可以參考“基本運算和輸入輸出”章節的內容。
更多細節部分,可以參考主流C語言參考書自行補充完整。需要指出,ASCII表、優先級與結合級表、輸入輸出函數轉換說明符表和常用轉義字符表,是初學C語言時最為重要的四個表,應該作為工具經常使用。
其余更深入的內容,在學到對應的知識后將一目了然。此時,就沒有必要去盲目補充了,與其沉溺於起點寸步不前,不如走向遠方,等學有所成時再回頭看起點,將恍然明悟,且獲益匪淺!
Part2 知識結構梳理