很多人第一次接觸 C 語言,都會覺得它有點「硬」。
沒有那麼多現成封裝,沒有太多語法糖,很多東西都得自己一步一步寫出來。
但也正因為如此,C 語言特別適合用來打基礎。
它會逼著你去理解:變數到底是什麼,輸入為什麼要傳地址,陣列為什麼能和迴圈配合,函數怎麼傳參,指標又為什麼總是繞不開。
如果這些最基礎的東西真正學明白了,後面無論繼續學 C++、Java、Python,還是接觸作業系統、嵌入式、資料結構,理解都會更紮實。
本文就按照初學者最容易建立認知的順序,把 C 語言的核心基礎串起來,幫你搭起一張完整的知識框架。
一、學 C 語言,先抓住三條主線
剛開始學 C 語言時,最容易犯的錯誤就是把它學成「背單詞」。
今天記住一個 if,明天記住一個 for,後天再去背 scanf、陣列、指標。
看起來學了很多,實際上腦子裡是一盤散沙。
更好的方式,是先抓住三條主線:
第一,資料怎麼存。
變數、陣列、結構體、字串,本質上都在解決「資訊放在哪裡」。
第二,程式怎麼控制流程。
順序執行、條件分支、迴圈重複,都是在回答「事情怎麼一步一步做」。
第三,程式怎麼找到資料。
這會貫穿 scanf、函數傳參、陣列、指標,甚至檔案操作。
只要沿著這三條主線往下學,很多看似零散的知識點都會自然連起來。
二、變數:程式為什麼能「記住」資料
程式要處理資料,首先就得能把資料存起來。
而變數,就是程式裡最基礎的「儲存單元」。
例如:
int age = 18;這句程式碼表示:定義一個名叫 age 的整型變數,並把值 18 存進去。
這裡有兩個基礎概念必須先弄清楚:識別字和資料型態。
1. 識別字:給資料起名字
變數名、函數名、陣列名,統稱為識別字。
識別字不是隨便寫的,它要滿足基本規則:
- 由字母、數字、底線組成
- 不能以數字開頭
- 不能和關鍵字重名
- 區分大小寫
例如:
int score;
int _num;
int age1;這些寫法都沒問題。
但下面這些就是不合法的:
int 2a;
int if;所以,學會定義變數的第一步,其實就是學會給資料起一個合法、清晰的名字。
2. 資料型態:決定變數能裝什麼
C 語言不是「隨便拿個變數就能裝任何東西」,每個變數都要先宣告型態。
常見基礎型態有:
int a = 10; // 整数
float b = 3.14; // 浮点数
char c = 'A'; // 字符這意味著變數不僅有名字,還有「這個盒子裡允許裝什麼」的限制。
初學階段一定要建立這個意識,因為它會影響你後面所有的輸入、輸出、運算和記憶體理解。
三、輸入輸出:程式如何和人互動
程式不是只在內部悄悄計算,它還要和人打交道。
最常見的互動方式,就是輸入和輸出。
1. 輸出:把結果顯示出來
C 語言中最常見的輸出函數是 printf。
例如:
printf("Hello C!\n");如果要輸出變數,就需要用到格式控制符:
int age = 18;
printf("%d\n", age);這裡 %d 表示「按整數格式輸出」。
常見格式說明符有:
%d:整數%f:浮點數%c:字元%s:字串
例如:
float price = 19.9;
char ch = 'A';
printf("%f\n", price);
printf("%c\n", ch);printf 最重要的不是把符號背下來,而是理解:
程式輸出資料時,必須知道要按什麼型態去解釋它。
2. 輸入:為什麼 scanf 經常帶 &
如果說 printf 是「把內容展示出來」,那麼 scanf 就是「把使用者輸入讀進來」。
例如:
int age;
scanf("%d", &age);這行程式碼的意思是:從鍵盤讀取一個整數,並存到變數 age 中。
有些人可能會有疑問,為什麼這裡寫的是 &age,而不是 age?
原因很簡單:
scanf 不是要讀取 age 當前的值,而是要把使用者輸入的內容「寫進 age 所在的位置」。
所以它需要的不是值,而是地址。
也就是說:
age表示變數中的值&age表示變數在記憶體中的地址
這個 &,其實已經把你帶進了 C 語言最核心的底層思維:
程式不僅處理值,還處理值所在的位置。
四、運算子與運算式:程式到底是怎麼「算」的
變數有了,輸入輸出也有了,接下來程式就要開始處理資料。
而處理資料,離不開運算子和運算式。
1. 算術運算子
最基本的算術運算子有:
+ - * / %例如:
int a = 10;
int b = 3;
printf("%d\n", a + b);
printf("%d\n", a % b);其中最值得新手注意的是 / 和 %。
整數除法
如果兩邊都是整數:
15 / 4結果是 3,不是 3.75。
因為整數除法只保留整數部分。
浮點除法
只要有一邊是浮點數:
15 / 4.0結果才會變成 3.75。
取模運算
15 % 4結果是 3,表示餘數。
% 只能用於整數,但它非常實用。
判斷奇偶、拆分數字、處理週期規律時,經常都要用到它。
2. 複合賦值
除了:
a = a + 3;也可以寫成:
a += 3;類似地還有:
a -= 3;
a *= 3;
a /= 3;
a %= 3;這些寫法在迴圈和陣列處理中尤其常見。
3. 邏輯運算
邏輯運算子用於組合多個條件:
!:非&&:與||:或
例如:
if (age >= 18 && age <= 60)
{
printf("符合条件\n");
}所以程式並不是只能判斷一個條件,它還可以把多個條件組合起來,一起做出決策。
五、分支:讓程式學會「做選擇」
現實問題裡,很多事情都不是順著往下做,而是「如果滿足某個條件,就執行 A;否則執行 B」。
這就是分支結構的作用。
1. if:最基礎的條件判斷
例如:
if (x > 0)
{
printf("x是一个正数");
}
else
{
printf("x不是一个正数");
}這類程式碼幾乎就是自然語言的直接翻譯:
- 如果條件成立,就執行前面的程式碼區塊
- 否則,就執行後面的程式碼區塊
2. 多分支判斷
如果情況更多,可以用 else if 繼續擴展:
if (score >= 90)
printf("A");
else if (score >= 80)
printf("B");
else if (score >= 70)
printf("C");
else if (score >= 60)
printf("D");
else
printf("E");這種結構特別適合處理「分段規則」,比如成績分級、費用計算、年齡劃分等。
3. switch:處理固定值更清晰
如果判斷條件是「某個變數等於哪個固定值」,switch 會更整齊:
switch (grade)
{
case 'A':
printf("优秀");
break;
case 'B':
printf("良好");
break;
default:
printf("其他");
}這裡最關鍵的一點是 break。
如果忘了寫,程式會繼續往下執行,出現「貫穿」的效果。
六、迴圈:讓程式學會重複做事
如果分支是「做選擇」,那麼迴圈就是「重複做」。
電腦最擅長的事情之一,就是把同一套規則準確地執行很多遍。
而迴圈,正是這種能力的體現。
1. while:條件成立就一直執行
int i = 1;
while (i <= 5)
{
printf("%d\n", i);
i++;
}這段程式碼會輸出 1 到 5。
while 的特點是:先判斷,再執行。
所以如果條件一開始就是假,迴圈可能一次都不執行。
2. do...while:至少先執行一次
int i = 1;
do
{
printf("%d\n", i);
i++;
} while (i <= 5);和 while 不同,do...while 是先執行一次,再判斷條件。
3. for:最常用的計數迴圈
for (int i = 1; i <= 5; i++)
{
printf("%d\n", i);
}for 把初始化、條件判斷和更新寫在一行裡,結構更緊湊,所以在實際程式設計中非常常見。
4. 迴圈的真正價值
初學時最常見的迴圈任務包括:
- 求和
- 統計個數
- 找最大值和最小值
- 走訪陣列
- 輸出某個範圍內滿足條件的數
所以迴圈不是單純的語法範本,而是一種很重要的程式設計思維:
把問題拆成「重複執行同一套步驟」的過程。
七、函數:把一段功能單獨封裝起來
當程式越來越長,所有程式碼都寫在 main 裡就會顯得很亂。
這時就需要函數。
函數可以理解為:
一段專門用來完成某個任務的程式碼區塊,並且可以被重複呼叫。
例如:
int add(int a, int b)
{
int c = a + b;
return c;
}呼叫時寫成:
int sum = add(10, 20);
printf("%d", sum);1. 函數為什麼重要
函數最核心的價值有兩個:
- 把複雜程式拆開,讓結構更清晰
- 把重複邏輯封裝起來,避免反覆寫同樣的程式碼
2. 參數和傳回值
函數中的參數,是把資料傳進去。
傳回值,是把結果帶出來。
這兩個概念看起來簡單,但它們幾乎決定了函數的全部意義。
3. 值傳遞和地址傳遞
這是學函數時非常關鍵的一步。
普通參數傳遞,本質上是把值複製一份給函數。
函數內部即使修改了參數,也不一定會影響外部變數。
如果傳進去的是地址,情況就不同了。
函數可以透過這個地址,直接操作外部變數所在的那塊記憶體。
這也是為什麼函數、scanf 和指標之間會有非常強的聯繫。
4. 陣列作為函數參數
陣列傳參尤其值得注意。
因為陣列作為參數傳入函數時,本質上傳的是首元素地址。
這意味著函數內部对陣列元素的修改,往往會直接影響原陣列。
這件事對理解「地址傳遞」非常重要。
八、陣列:當一個變數不夠用時
如果程式只處理一個數,一個變數就夠了。
但如果要處理 10 個成績、5 個座標、一個班的分數列表,單個變數顯然不夠。
這時就要用陣列。
1. 一維陣列:一組相同型態的資料
int arr[5] = {1, 2, 3, 4, 5};這表示定義一個包含 5 個整數的陣列。
陣列的本質,可以理解為:
把一組同型態的資料按順序放在一起。
2. 索引從 0 開始
陣列最重要的規則之一,就是索引從 0 開始。
arr[0] // 第一个元素
arr[1] // 第二个元素這個小細節,是初學者最容易犯錯的地方之一。
3. 陣列和迴圈是天然搭檔
陣列的常見操作,幾乎都要和迴圈搭配使用:
for (int i = 0; i < 5; i++)
{
printf("%d\n", arr[i]);
}走訪、求和、查找、統計,基本都離不開這個組合。
4. 二維陣列:陣列的陣列
例如:
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};二維陣列很適合表示表格、矩陣、成績單這類二維資料。
九、指標:理解 C 語言最關鍵的一步
很多人一聽到指標就緊張。
它確實是 C 語言裡比較抽象的部分,但也是最能體現這門語言底層特性的地方。
1. 指標是什麼
一句話先記住:
指標是存放地址的變數。
例如:
int a = 10;
int *p = &a;這裡:
a是普通變數&a是a的地址p是指標變數p裡存的是a的地址
2. p 表示什麼
如果 p 存的是 a 的地址,那麼:
*p表示透過這個地址,取出對應位置上的值。
例如:
printf("%d\n", *p);輸出的就是 10。
3. 一級指標和二級指標
如果一個指標變數本身也有地址,那麼就可以繼續定義「指向指標的指標」:
int a = 10;
int *p = &a;
int **pp = &p;雖然看起來繞,但本質上只是「地址也可以繼續被儲存」。
4. 指標和陣列關係很深
例如:
int arr[5] = {10, 20, 30, 40, 50};訪問第三個元素時:
arr[2]
*(arr + 2)在很多場景中是等價的。
這說明陣列名和地址之間存在非常緊密的聯繫,而這正是理解陣列、函數傳參和指標運算的關鍵。
十、結構體、字串和預處理
當前面的基礎都打穩以後,C 語言就會慢慢從「練語法」過渡到「表達真實物件」。
1. 結構體:把多個屬性組合到一起
例如:
struct Person
{
char name[10];
int age;
float height;
};這意味著一個「人」可以同時擁有姓名、年齡、身高等多個屬性。
訪問結構體成員時,常用寫法是:
person.age如果是結構體指標,則要寫成:
p->age結構體的重要意義在於,它讓程式不只是處理單個值,而是開始處理「一個物件」。
2. 字串
在 C 語言中,字串其實不是獨立資料型態,而是字元陣列。
例如:
char str[] = "hello";它的本質是若干字元連續存放,並以 \0 作為結束標記。
理解這一點,對後面學習字串長度、字元陣列空間、字串處理函數都非常重要。
3. #define:編譯前替換
例如:
#define PI 3.14這不是變數,而是預處理階段進行的文字替換。
入門階段知道這一點就夠了:
它的核心不是「存資料」,而是「在編譯前先替換程式碼內容」。
十一、檔案:讓程式和外部資料打交道
學到這裡,程式就不只是和鍵盤、螢幕打交道了。
它還可以讀取和寫入檔案。
1. 檔案操作的基本入口
在 C 語言中,檔案通常透過檔案指標來操作。
例如:
FILE *fp = fopen("output.txt", "w");這表示以寫入方式開啟一個檔案。
2. 常見開啟方式
常見模式有:
"r":唯讀"w":只寫"a":追加"rb"/"wb":二進位方式讀寫- 帶
+:讀寫結合
開啟方式決定了程式能對檔案做什麼。
3. 常見檔案讀寫函數
例如:
fgetc/fputcfgets/fputs
從理解上說,檔案操作和前面的輸入輸出本質是一致的:
只不過輸入輸出的物件,從鍵盤和螢幕,變成了磁碟上的檔案。
十二、一張完整的圖
以上內容是一條逐層展開的路徑:
- 從變數開始,學會存資料
- 用輸入輸出和程式建立互動
- 用運算子處理資料
- 用分支和迴圈控制流程
- 用函數拆分任務
- 用陣列處理一批資料
- 用指標理解地址和記憶體
- 再擴展到結構體、字串、檔案這些更真實的應用場景
如果把 C 語言基礎看作蓋房子,那麼變數、輸入輸出、分支、迴圈、函數、陣列、指標,就是一層一層往上搭起來的結構。
單獨看,每個知識點都不算特別複雜。但只有把它們融會貫通,你才會真正從「會寫幾個例子」,走到「開始理解程式設計」。
這也是為什麼很多人覺得 C 語言難,但真正學進去之後,又會覺得它特別基礎。
因為它不是在教你「怎麼拼程式碼」,而是在教你:
電腦程式到底是如何運作的。