干货 | 如何系统学习 C 语言?
關注、星標公眾號,直達精彩內容
C 語言應該是絕大部分同學的編程第一課。
對于非 CS 專業的同學,學 C 語言主要是掌握一些基本的編程方法,C 語言只是媒介。
但是對于 CS 科班的同學,C 語言是后續的計組、體系結構、操作系統、編譯原理等課程的基石,對于 C 語言本身甚至程序設計語言基礎原理的深入理解都是應該掌握的。
一、一圖勝千言
如果你不想看冗余的文字,直接看我畫的這個思維導圖即可:
二、C 語言易學難精?
很多同學都反映 C 語言難。
實際上,相比 C++、Java 之類的更加現代的語言, C 語言本身的語法特性非常少,不像 C++ 成了一鍋大雜燴。
C 語言本身只包含了編程語言最基本的語法,比如變量、if、else、for、while、枚舉、結構體等,外加一個指針。
但是為什么大家都覺得難呢?
說下我大一時覺得難的原因吧,主要兩點:
1. 庫太少,太原始
用 C 語言寫個稍微復雜點的項目,你需要上來先把數據結構、常見算法先實現一遍,更別說字符串,序列化這些了。
比如 Redis 里 SDS、LIST、ZSET、HASH等。
這其實對新手極其的不友好。
想做點有趣的東西,來,先寫個鏈表?
而在 Java 里直接 New 一個 LinkedLits、HashMap,簡直不要太高效。
再到后來,學了 Python,才發現這才是編程的高級形態,寫個爬蟲直接 import xx,幾句話就完事了。
而在 C 語言里,你需要裸寫 Socket 發網絡包,還要解析 HTTP 協議,還要序列化 JSON,處理 HTTPS 這些(當然,你也可以導入庫,但是由于 C/C++ 弱雞等同于沒有的包管理,也挺麻煩的。
這就是新手學 C 容易被勸退的原因,做不出好玩的東西,全是一堆黑框框。
2. 內存、指針
另外,常另 C 語言初學者感到頭疼的就是指針了。
指針其實本身不難,就是變量的地址嘛。
但是問題在于地址是個什么東西?
理解地址,就需要理解內存,但是鑒于大多數同學學習 C 語言,都是在大一,那時候沒有計算機基礎知識,其實理解起來還是稍微吃力的。
內存,其實也很簡單啊,你就把它當做一個黑盒,提供了讀和寫的能力。
就像快遞柜一樣,提供了存東西、放東西的能力:
讀哪里?寫哪里?
當然是需要地址啊,地址就跟快遞柜上的編號一樣,而快遞柜格子里就相對于內存中真正存放的內容。
記住這張快遞柜的照片,其實指針你就理解了。
什么是二級指針?
就是快遞柜格子里放的是另外一個格子的編號,對應到 C 語言舉個例子:
int?a?=?10; int?*pa?=?&a; int?**ppa?=?&pa;ppa 所指向的內存存放的內容是 pa 的地址,pa 存放的是 a 的地址(就不畫圖了,腦補
那你要問了,那指針和二級指針以及更多級的指針有什么區別呢?
為什么二級指針就要兩個**?
很簡單啊,不用兩個 ** 的話,你怎么告訴編譯器,這個地方放的其實是另外一個內存的地址?
這樣編譯器才能去做語法檢查,不然誰知道你這是放的變量地址還是另外一個指針的地址啊。
更加詳細的內容其實我在這篇指針的文章中講過:
為什么指針被譽為 C 語言靈魂?
不過現在站在我的角度,覺得指針很簡單,似乎很好理解,也許是知識詛咒的原因。
知識詛咒:指的就是一旦我們自己知道某樣東西,我們就會發現很難想象不知道它的時候會是什么樣子。
后來接觸到 Java,如同發現了新大陸一般。
在 C 語言里,申請一個內存,你得隨時記得在合適的地方釋放。
釋放得不合適?對不起 coredump 隨時等著你。
忘了釋放?對不起,內存泄露等著你~
亂寫指針?對不起,內存越界等著你~
棧內存越界?VS下,燙燙燙等著你~
這些東西想必是每一位 C Programmer 的家常便飯了。
而在 Java 這類更加高級語言中,直接 new 一個就行了。
好了,扯淡完畢,在這里給出一條系統化學習 C 語言的路線吧:
第一階段:初學少看書,多看視頻
這真的是血淚教訓,我大一會傻乎乎的去把課本看一遍,然后做課本后面編程練習題。
學得那叫一個艱難呀,大家都知道,課本為了保留其嚴謹性和全面性,往往都具有一個特點,那就是「不說人話」。
對于 C 語言,初學者有一個難點需要克服,就是容易遇到各種編譯、鏈接錯誤,而且不知道怎么解決:
比如這種很初級的報錯,但是初學者往往看到就慌了。
遇到這種情況,我的建議是仔細讀報錯的提示,解決方法往往就在這些 note 中,如果實在解決不了,就復制 note 去 Google 上搜。
這個階段你需要三份資料:
一是補 CS 基礎概念,也就是計算機導論
二是一本 C 語言的好書。
三是一個優質的 C 語言視頻
對于每一點,我都只推薦一份我覺得最合適的,避免你陷入選擇困難癥:
計算機導論
CS 50,這是哈佛的一門計算機入門神課,忘了是在大一下還是大二看的了,當時覺得如獲至寶。鏈接如下:
https://cs50.harvard.edu/college/2021/spring
讓我現在還記憶尤新的一個點,是這個老師講到 binary search 的時候,直接舉了查字典這個過程,然后現場手撕字典。。。
另外,這門課是用 C 語言作為教學語言的,非常難得。
因為現在國外很多 CS 名校的導論課都會采用類似 Python、Schema 這樣的語言。
但其實你會發現,在 CS 50,不會講多少 C 語言的語法,C 語言只是作為一種傳遞編程思想、引領你入門計算機的媒介。
而不是在教 C 語言。
C 語言視頻
不多說了,推薦一個我以前在地鐵都在刷的,浙大翁凱老師教授的,直接去中國大學 MOOC 搜索即可,這是鏈接:
https://www.icourse163.org/course/ZJU-199001
說到這,我不得不多說兩句翁凱老師了,我看了好幾門他的課,最直觀的感受是:
講解透徹、聲音好聽,而且特別注重細節,貼一張浙大匿名教室系統關于翁凱老師的評價吧:
一句話,翁凱老師是真的想把計算機內部原理、編程語言以深入淺出的方式教給大家。
C語言書
《C程序設計語言》,一本被稱作 C 語言圣經的書。
在短小的篇幅中,涵蓋了 <stdio.h>、<string.h> 中的大部分例子,習題也都是經典,從 hello world 開始,到二分查找、二叉樹、快排、哈希表等,甚至還用遞歸下降寫了詞法分析,幫你理解復雜的聲明。
不過要看懂里面的每一個例子,也是有一定難度的,需要有一點點基礎,但是不妨礙作為入門書,可以多看幾遍。
對了,一直說學編程要多寫,但是很多初學者也不知道寫什么。
在這里,我給出一些學完 C 語言基本語法后,可以練手的例子:
鏈表
就用 C 語言把鏈表翻來覆去的寫,從最基本的鏈表插入、刪除、單向、雙向、環裝鏈表。
到鏈表反轉、合并、分割等。
別看基礎,但是很多同學到大四了,可能都寫不對,這里考察是否足夠細心、邏輯是否縝密。
會不會操作著就把鏈給斷了。
寫點小東西
比如圖書管理系統、俄羅斯方塊、貪吃蛇之類。
這種代碼量大多在 500 - 1000,會綜合運用函數、文件操作、動態內存、指針這些關鍵的東西。
第二階段:搞懂內存,看書、寫代碼
這個階段,是需要掌握一些計算機系統知識才能學好的,比如虛擬地址就和操作系統相關了,而函數調用棧這些又和匯編相關。
又比如很多學了很久的同學,還不太清楚變量的聲明和定義區別,extern 又有什么作用,這些實際上就需要理解內存分區的東西。
C 語言的核心就在于指針、內存,能不能學好、用好 C 語言,更多在于是否擁有扎實的計算機結構、存儲、運算原理方面的知識。
所以強烈建議在學習 C 語言的同時去了解一下補碼、數的二進制表示、內存、匯編等知識,尤其是內存和匯編,這兩個對于深刻理解指針和熟練運用有很大的幫助。
我就不仔細介紹了,要介紹的書都在這張思維導圖里了。
深入學習指針
《C和指針》、《深入理解C指針》,真的是涉及指針方方面面的好書,墻裂推薦。
編譯、鏈接
這倆兄弟懂了其實也不能幫你提高寫代碼的水平,主要是對于一些編譯、鏈接過程的報錯,更加的明確,不至于懵。
比如鏈接過程中常見的錯誤是符號未找到(undefined reference)和符號重定義(redefinition)
當你熟悉鏈接過程,符號查找過程之后,解決對應的報錯也會得心應手。
匯編
C 語言之下就是匯編,會匯編,你就能直接把 C 語言衣服扒掉,看看背后的實現,比如大家都在討論數組和指針有什么區別?
你去寫個程序,然后 gcc -S 一下,看下匯編代碼,你就會發現沒啥區別。。。
匯編不需要會寫,會看懂部分記得,大可不必去刻意的記住各種指令、尋址方式。
好了,今天的 C 語言學習之路就到這里了,其實還有很多東西沒提,比如 Linux C 方向的。
主要為了突出學習 C 語言本身,不想喧賓奪主,讓大家迷失了方向。
另外,我推薦的這些書籍,我也都匯總了:
這一套學完,C 語言基本問題不大。
有需要的可以點擊下方公眾號,關注后回復「C語言」即可。
祝大家周末愉快~~
總結
以上是生活随笔為你收集整理的干货 | 如何系统学习 C 语言?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为p20pro和p30pro区别
- 下一篇: 鸿蒙2.0都来了,快搭个环境玩起来吧!