0%
從零到精通 — C語言編程課程

C 語言
繁體中文教學

C 語言由 Dennis Ritchie 於 1972 年創造,C 語言是所有程式設計師的基礎。學習 C,你將真正理解電腦的運作原理,掌握記憶體管理與底層效能優化,立即在香港編程學院C語言自學,把C語言從入門到精通。

18+
章節
50+
程式範例
10
互動測驗
1972
誕生年份
#include <stdio.h>
/* 我的第一個 C 程式 */
int main() {
  printf("Hello, World!\n");
  return 0;
}

📋 課程目錄

🚀
C 語言簡介
了解 C 的歷史、特性與應用
CH.01

C 語言由 Dennis Ritchie 於 1972 年在貝爾實驗室開發,至今已超過 50 年歷史,仍然是世界上最重要的程式語言之一。

📅
誕生年份
1972 年,Dennis Ritchie 在貝爾實驗室開發
🏆
TIOBE 排名
長期位居前三,超過 40 年不衰的程式語言
執行效率
接近機器語言的速度,幾乎無效能損耗
🌍
應用廣泛
OS、嵌入式、資料庫、遊戲引擎核心

C 語言的應用領域

作業系統 嵌入式系統 資料庫引擎 遊戲引擎 網路協議 驅動程式
🌟 為什麼學習 C 語言?
C 語言是 Python、Java、C++、C# 等現代語言的基礎。學好 C,你將真正理解電腦的底層原理:記憶體如何分配、指標如何運作、資料如何在記憶體中儲存。這些知識會讓你成為更優秀的程式設計師。
C 語言
✅ 程序式語言
✅ 極高執行效率
✅ 底層記憶體控制
✅ 標準函式庫精簡
✅ 嵌入式首選
❌ 無內建OOP
C++ 語言
✅ 物件導向+程序式
✅ 高執行效率
✅ 豐富標準函式庫
✅ 模板泛型程式
✅ 遊戲/應用開發
❌ 語法較複雜
C — 第一個程式
hello.c
#include <stdio.h> /* 這是一個單行/多行註解 C 語言的起點:Hello World */ int main() { printf("Hello, World!\n"); printf("歡迎學習 C 語言!\n"); return 0; // 程式正常結束 }
▶ 輸出結果
Hello, World!
歡迎學習 C 語言!
🔧
環境安裝
設定 GCC 編譯器與開發環境
CH.02
1
下載 MinGW-w64
前往 mingw-w64.org 下載最新 installer,選擇 x86_64 架構安裝。
2
設定環境變數
C:\mingw64\bin 加入系統 PATH 環境變數,讓終端機找到 gcc 指令。
3
安裝 VS Code
下載 Visual Studio Code,安裝 C/C++ Extension Pack 擴充套件。
4
驗證安裝
開啟終端機輸入 gcc --version,看到版本號表示安裝成功!
1
安裝 Xcode Command Line Tools
開啟終端機,輸入 xcode-select --install,這會自動安裝 clang/gcc。
2
或透過 Homebrew 安裝 GCC
先安裝 Homebrew,再執行 brew install gcc 取得最新版本。
3
驗證並安裝 VS Code
輸入 gcc --version,確認可執行。安裝 VS Code 加上 C/C++ 擴充套件。
1
Ubuntu/Debian 安裝 GCC
執行 sudo apt-get update && sudo apt-get install gcc build-essential
2
驗證安裝
執行 gcc --version,確認 GCC 版本正確顯示。

C 程式編譯流程

Shell — 編譯與執行
# 步驟1:撰寫程式碼,儲存為 hello.c # 步驟2:使用 GCC 編譯 gcc hello.c -o hello # 加上警告選項(建議開發時使用) gcc -Wall -Wextra -o hello hello.c # 步驟3:執行程式 ./hello # Linux/macOS hello.exe # Windows # 完整除錯編譯 gcc -g -o hello hello.c # -g 加入偵錯資訊
💡 提示: 建議使用 -Wall 編譯選項,它會顯示所有警告,幫助你養成良好的程式習慣,及早發現潛在問題。
📝
基礎語法
C 語言程式的結構與規則
CH.03

每個 C 程式都有固定的結構。理解這個結構是學習 C 語言的第一步。

C — 程式結構解析
// 1. 前置處理指令(引入標頭檔) #include <stdio.h> // 標準輸出入 #include <stdlib.h> // 一般工具 #include <string.h> // 字串處理 // 2. 全域變數(在所有函式外宣告) int globalVar = 100; // 3. 函式原型宣告 void greet(char *name); // 4. 主函式(程式進入點) int main() { // 5. 區域變數 int age = 20; char name[] = "小明"; // 6. 呼叫函式 greet(name); printf("年齡: %d\n", age); return 0; // 回傳 0 表示成功 } // 7. 函式定義 void greet(char *name) { printf("你好,%s!\n", name); }
▶ 輸出結果
你好,小明!
年齡: 20
⚠️ 重要規則:
• 每條語句以 ; 結束
• 程式區塊用 { } 括起來
• C 語言區分大小寫mainMain
main() 是程式唯一的進入點
return 0 表示程式正常結束

常用格式說明符

格式符說明範例
%d整數(十進位)printf("%d", 42);
%f浮點數printf("%f", 3.14);
%.2f浮點數(保留2位小數)printf("%.2f", 3.14159);
%c字元printf("%c", 'A');
%s字串printf("%s", "Hi");
%p指標地址printf("%p", &x);
%x十六進位printf("%x", 255);
%o八進位printf("%o", 8);
%ld長整數printf("%ld", 1000000L);
%%印出 % 符號printf("100%%");
📦
變數與資料型態
int, float, char, double, bool
CH.04
型態大小範圍格式符範例
char1 byte-128 ~ 127%c / %dchar c = 'A';
unsigned char1 byte0 ~ 255%uunsigned char uc = 200;
int4 bytes-2,147,483,648 ~ 2,147,483,647%dint n = 42;
long4/8 bytes依平台而定%ldlong l = 10000L;
long long8 bytes極大整數範圍%lldlong long ll = 999LL;
float4 bytes~6-7 位有效數字%ffloat f = 3.14f;
double8 bytes~15-17 位有效數字%lfdouble d = 3.14;
_Bool1 byte0 (false) 或 1 (true)%d_Bool b = 1;
C — 變數宣告與使用
#include <stdio.h> #include <stdbool.h> // bool 型態 int main() { // 基本型態宣告 int age = 25; double price = 99.90; char grade = 'A'; bool passed = true; // 常數 (const 修飾) const double PI = 3.14159265; // 多變數同時宣告 int x = 10, y = 20, z = 30; // 型態大小 printf("int 大小: %zu bytes\n", sizeof(int)); printf("double 大小: %zu bytes\n", sizeof(double)); // 型態轉換 int a = 7, b = 2; double result = (double)a / b; // 強制轉型 printf("7/2 = %.2f\n", result); printf("年齡:%d 成績:%c 通過:%s\n", age, grade, passed ? "是" : "否"); return 0; }
▶ 輸出結果
int 大小: 4 bytes
double 大小: 8 bytes
7/2 = 3.50
年齡:25 成績:A 通過:是
運算子
算術、比較、邏輯、位元運算
CH.05
運算子說明範例結果
+加法5 + 38
-減法5 - 32
*乘法5 * 315
/除法7 / 23(整數除法)
%取餘數7 % 31
++遞增x++x+1
--遞減x--x-1
運算子說明範例結果
==等於5 == 51 (true)
!=不等於5 != 31 (true)
>大於5 > 31 (true)
<小於5 < 30 (false)
>=大於等於5 >= 51 (true)
<=小於等於3 <= 51 (true)
運算子說明範例結果
&&AND(且)1 && 00 (false)
||OR(或)1 || 01 (true)
!NOT(非)!10 (false)
運算子說明等同於
=指定x = 5
+=加後指定x = x + 5
-=減後指定x = x - 5
*=乘後指定x = x * 5
/=除後指定x = x / 5
%=模後指定x = x % 5
C — 運算子綜合示範
#include <stdio.h> int main() { int a = 10, b = 3; printf("=== 算術運算 ===\n"); printf("%d + %d = %d\n", a, b, a+b); printf("%d %% %d = %d\n", a, b, a%b); printf("=== 遞增/遞減 ===\n"); int x = 5; printf("x++ = %d\n", x++); // 先用再加 printf("++x = %d\n", ++x); // 先加再用 printf("=== 三元運算子 ===\n"); int score = 75; char *result = (score >= 60) ? "及格" : "不及格"; printf("成績: %s\n", result); return 0; }
▶ 輸出結果
=== 算術運算 ===
10 + 3 = 13
10 % 3 = 1
=== 遞增/遞減 ===
x++ = 5
++x = 7
=== 三元運算子 ===
成績: 及格
💬
輸出與輸入
printf / scanf / gets / getchar 完整指南
CH.06
C — 輸出與輸入
#include <stdio.h> int main() { int age; double weight; char name[50]; // 讀取整數 printf("請輸入年齡: "); scanf("%d", &age); // 讀取浮點數 printf("請輸入體重(kg): "); scanf("%lf", &weight); // 讀取字串(不含空格) printf("請輸入姓名: "); scanf("%49s", name); // 防止緩衝區溢位 // 格式化輸出 printf("\n=== 個人資料 ===\n"); printf("姓名: %-10s\n", name); // 左對齊 10 字元 printf("年齡: %5d 歲\n", age); // 右對齊 5 字元 printf("體重: %6.1f kg\n", weight); // 保留1位小數 // 計算 BMI double height = 1.70; double bmi = weight / (height * height); printf("BMI: %.2f\n", bmi); return 0; }
⚠️ 安全警告: 使用 scanf 讀取字串時,務必限制寬度(如 %49s),避免緩衝區溢位漏洞(Buffer Overflow)。在安全要求高的場合,建議使用 fgets() 代替。
🔀
條件判斷
if / else if / else / switch
CH.07
C — if/else 成績判斷
#include <stdio.h> int main() { int score = 85; char grade; // if / else if / else if (score >= 90) { grade = 'A'; printf("優秀!繼續保持\n"); } else if (score >= 80) { grade = 'B'; printf("良好!\n"); } else if (score >= 70) { grade = 'C'; printf("普通,需要加強\n"); } else { grade = 'F'; printf("不及格,要努力了\n"); } printf("分數: %d,等級: %c\n", score, grade); // switch 陳述式 int day = 3; switch (day) { case 1: printf("星期一\n"); break; case 2: printf("星期二\n"); break; case 3: printf("星期三\n"); break; case 6: case 7: printf("週末!\n"); break; default: printf("其他\n"); } return 0; }
▶ 輸出結果
良好!
分數: 85,等級: B
星期三
🔄
迴圈
for / while / do-while / break / continue
CH.08
C — 三種迴圈比較
#include <stdio.h> int main() { // 1. for 迴圈(已知次數) printf("for 迴圈: "); for (int i = 1; i <= 5; i++) { printf("%d ", i); } printf("\n"); // 2. while 迴圈(條件成立) printf("while 迴圈: "); int n = 1; while (n <= 5) { printf("%d ", n); n++; } printf("\n"); // 3. do-while 迴圈(至少執行一次) printf("do-while: "); int m = 1; do { printf("%d ", m); m++; } while (m <= 5); printf("\n"); // break 與 continue printf("奇數(1-10): "); for (int i = 1; i <= 10; i++) { if (i % 2 == 0) continue; // 跳過偶數 printf("%d ", i); } printf("\n"); // 九九乘法表 printf("九九乘法表:\n"); for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 9; j++) { printf("%d*%d=%2d ", i, j, i*j); } printf("\n"); } return 0; }
▶ 輸出結果
for 迴圈: 1 2 3 4 5
while 迴圈: 1 2 3 4 5
do-while: 1 2 3 4 5
奇數(1-10): 1 3 5 7 9
九九乘法表:
1*1= 1 1*2= 2 ... 1*9= 9
2*1= 2 ... 2*9=18
3*1= 3 ... 3*9=27
📊
陣列
一維、二維陣列與陣列排序
CH.09
C — 陣列操作完整示範
#include <stdio.h> int main() { // 一維陣列宣告與初始化 int scores[] = {85, 92, 78, 96, 88}; int n = sizeof(scores) / sizeof(scores[0]); // 計算總和與平均 int sum = 0, max = scores[0], min = scores[0]; for (int i = 0; i < n; i++) { sum += scores[i]; if (scores[i] > max) max = scores[i]; if (scores[i] < min) min = scores[i]; } printf("總和=%d 平均=%.1f 最高=%d 最低=%d\n", sum, (double)sum/n, max, min); // 氣泡排序(由小到大) for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) { if (scores[j] > scores[j+1]) { int tmp = scores[j]; scores[j] = scores[j+1]; scores[j+1] = tmp; } } } printf("排序後: "); for (int i = 0; i < n; i++) printf("%d ", scores[i]); printf("\n"); // 二維陣列(矩陣) int matrix[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; printf("3x3 矩陣:\n"); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) printf("%3d", matrix[i][j]); printf("\n"); } return 0; }
▶ 輸出結果
總和=439 平均=87.8 最高=96 最低=78
排序後: 78 85 88 92 96
3x3 矩陣:
1 2 3
4 5 6
7 8 9
🔡
字串
字元陣列與 string.h 函式庫
CH.10
📌 C 字串本質: C 語言沒有內建字串型態。字串是以 '\0'(null terminator)結尾的字元陣列。例如 "Hello" 在記憶體中儲存為 H, e, l, l, o, \0(共6個byte)。
函式說明範例
strlen(s)字串長度strlen("Hello") → 5
strcpy(dst,src)複製字串strcpy(b, "World")
strcat(dst,src)串接字串strcat(a, b)
strcmp(a,b)比較字串(0=相等)strcmp("a","b") → -1
strchr(s,c)尋找字元strchr("Hello",'l')
strstr(s,sub)尋找子字串strstr("Hello","ell")
toupper(c)轉大寫字元toupper('a') → 'A'
sprintf(buf,fmt,...)格式化寫入字串sprintf(s,"%d",42)
C — 字串操作
#include <stdio.h> #include <string.h> #include <ctype.h> int main() { char s1[50] = "Hello"; char s2[] = "World"; printf("長度: %zu\n", strlen(s1)); strcat(s1, ", "); strcat(s1, s2); printf("串接: %s\n", s1); // 反轉字串 char str[] = "ABCDE"; int len = strlen(str); for (int i = 0; i < len/2; i++) { char tmp = str[i]; str[i] = str[len-1-i]; str[len-1-i] = tmp; } printf("反轉: %s\n", str); // 逐字轉小寫 char upper[] = "HELLO C"; for (int i = 0; upper[i]; i++) upper[i] = tolower(upper[i]); printf("小寫: %s\n", upper); return 0; }
▶ 輸出結果
長度: 5
串接: Hello, World
反轉: EDCBA
小寫: hello c
函式
定義、傳值/傳址、遞迴函式
CH.11
C — 函式全面示範
#include <stdio.h> // 傳值(不影響原變數) void swapByValue(int a, int b) { int tmp = a; a = b; b = tmp; printf("函式內: a=%d b=%d\n", a, b); } // 傳址(影響原變數) void swapByRef(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } // 遞迴:計算階乘 long long factorial(int n) { if (n <= 1) return 1; return n * factorial(n - 1); } // 遞迴:費氏數列 int fib(int n) { if (n <= 1) return n; return fib(n-1) + fib(n-2); } // 函式指標 int add(int a, int b) { return a + b; } int mul(int a, int b) { return a * b; } int main() { int x = 10, y = 20; swapByValue(x, y); printf("傳值後: x=%d y=%d\n", x, y); // 不變 swapByRef(&x, &y); printf("傳址後: x=%d y=%d\n", x, y); // 改變 printf("10! = %lld\n", factorial(10)); printf("費氏數列: "); for(int i=0; i<10; i++) printf("%d ", fib(i)); printf("\n"); // 函式指標 int (*op)(int, int); op = add; printf("add(3,4) = %d\n", op(3,4)); op = mul; printf("mul(3,4) = %d\n", op(3,4)); return 0; }
▶ 輸出結果
函式內: a=20 b=10
傳值後: x=10 y=20
傳址後: x=20 y=10
10! = 3628800
費氏數列: 0 1 1 2 3 5 8 13 21 34
add(3,4) = 7
mul(3,4) = 12
👉
指標
C 語言最強大也最精華的特性
CH.12
🔑 指標的本質: 指標是一個儲存「記憶體地址」的變數。int *p = &x 表示 p 儲存變數 x 的地址。*p 表示取得該地址的值(解參考)。
📌 記憶體模型示意圖
0x1000
42
int x = 42;
0x2000
0x1000
int *p = &x; // 儲存 x 的地址
*p == x == 42 ✓  &x == p == 0x1000 ✓
C — 指標完整示範
#include <stdio.h> int main() { int x = 42; int *p = &x; // p 指向 x printf("x 的值: %d\n", x); printf("x 的地址: %p\n", (void*)&x); printf("p 的值(地址): %p\n", (void*)p); printf("*p(解參考): %d\n", *p); // 透過指標修改值 *p = 100; printf("修改後 x = %d\n", x); // 指標與陣列(陣列名就是指標) int arr[] = {10, 20, 30, 40, 50}; int *ap = arr; printf("陣列元素: "); for (int i = 0; i < 5; i++) printf("%d ", *(ap + i)); // 指標算術 printf("\n"); // 雙重指標 int **pp = &p; printf("**pp = %d\n", **pp); // NULL 指標 int *null_p = NULL; if (null_p == NULL) printf("這是 NULL 指標(安全檢查)\n"); return 0; }
▶ 輸出結果
x 的值: 42
x 的地址: 0x7fff...(每次不同)
p 的值(地址): 0x7fff...
*p(解參考): 42
修改後 x = 100
陣列元素: 10 20 30 40 50
**pp = 100
這是 NULL 指標(安全檢查)
🏗️
結構體
struct / typedef / union / enum
CH.13
C — 結構體完整示範
#include <stdio.h> #include <string.h> // 定義結構體 typedef struct { char name[50]; int age; double salary; } Employee; // 結構體函式 void printEmployee(Employee *e) { printf("姓名:%-10s 年齡:%3d 薪資:%.0f\n", e->name, e->age, e->salary); } // 列舉型態 typedef enum { MON, TUE, WED, THU, FRI, SAT, SUN } Day; int main() { // 初始化方式1:逐欄位 Employee emp1; strcpy(emp1.name, "陳小明"); emp1.age = 28; emp1.salary = 55000; // 初始化方式2:指定初始化 Employee emp2 = {"林美玲", 32, 72000}; // 使用函式指標操作 printEmployee(&emp1); printEmployee(&emp2); // 結構體陣列 Employee team[] = { {"王大同", 25, 48000}, {"張志豪", 35, 88000} }; int size = sizeof(team)/sizeof(team[0]); printf("=== 團隊成員 ===\n"); for(int i=0; i<size; i++) printEmployee(&team[i]); // 列舉使用 Day today = WED; if (today == WED) printf("今天星期三\n"); return 0; }
▶ 輸出結果
姓名:陳小明 年齡: 28 薪資:55000
姓名:林美玲 年齡: 32 薪資:72000
=== 團隊成員 ===
姓名:王大同 年齡: 25 薪資:48000
姓名:張志豪 年齡: 35 薪資:88000
今天星期三
💾
記憶體管理
malloc / calloc / realloc / free
CH.14
Stack(堆疊)
✅ 自動管理記憶體
✅ 速度極快
✅ 區域變數、函式參數
❌ 大小有限(通常幾MB)
❌ 函式結束即銷毀
Heap(堆積)
✅ 手動控制大小
✅ 生命週期可控
✅ 動態分配大型資料
❌ 必須手動 free
❌ 速度略慢於 stack
C — 動態記憶體配置
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int n = 5; // malloc: 配置 n 個 int 的空間(未初始化) int *arr = (int*)malloc(n * sizeof(int)); if (arr == NULL) { printf("記憶體配置失敗!\n"); return 1; } for(int i=0; i<n; i++) arr[i] = (i+1) * 10; // calloc: 配置並初始化為0 int *arr2 = (int*)calloc(n, sizeof(int)); // realloc: 重新調整大小 arr = (int*)realloc(arr, (2*n) * sizeof(int)); for(int i=n; i<2*n; i++) arr[i] = (i+1) * 10; printf("動態陣列: "); for(int i=0; i<2*n; i++) printf("%d ", arr[i]); printf("\n"); // 動態結構體陣列 char **names = (char**)malloc(n * sizeof(char*)); const char *nameList[] = {"小明","小華","小美","大雄","靜香"}; for(int i=0; i<n; i++) { names[i] = (char*)malloc(20); strcpy(names[i], nameList[i]); } printf("名單: "); for(int i=0; i<n; i++) printf("%s ", names[i]); // 釋放記憶體(重要!) for(int i=0; i<n; i++) free(names[i]); free(names); free(arr); free(arr2); printf("\n記憶體已釋放\n"); return 0; }
▶ 輸出結果
動態陣列: 10 20 30 40 50 60 70 80 90 100
名單: 小明 小華 小美 大雄 靜香
記憶體已釋放
⚠️ 記憶體洩漏(Memory Leak): 每個 malloc/calloc/realloc 必須有對應的 free()。釋放後將指標設為 NULL,避免使用懸空指標(Dangling Pointer)。
📁
檔案處理
fopen / fread / fwrite / fclose
CH.15
模式說明檔案不存在
"r"讀取錯誤
"w"寫入(覆蓋)建立新檔
"a"附加寫入建立新檔
"r+"讀取+寫入錯誤
"w+"讀取+寫入(覆蓋)建立新檔
"rb"二進位讀取錯誤
"wb"二進位寫入建立新檔
C — 檔案讀寫操作
#include <stdio.h> #include <stdlib.h> int main() { // ===== 寫入文字檔 ===== FILE *fp = fopen("data.txt", "w"); if (!fp) { perror("開啟檔案失敗"); return 1; } fprintf(fp, "第一行:C 語言檔案處理\n"); fprintf(fp, "第二行:分數 %d\n", 95); fputs("第三行:Hello File!\n", fp); fclose(fp); printf("✓ 寫入完成\n"); // ===== 讀取文字檔 ===== fp = fopen("data.txt", "r"); if (!fp) { perror("開啟失敗"); return 1; } char line[256]; printf("檔案內容:\n"); while (fgets(line, sizeof(line), fp)) printf(" %s", line); fclose(fp); // ===== 二進位檔案 ===== int nums[] = {10, 20, 30, 40, 50}; fp = fopen("nums.bin", "wb"); fwrite(nums, sizeof(int), 5, fp); fclose(fp); int read_nums[5]; fp = fopen("nums.bin", "rb"); fread(read_nums, sizeof(int), 5, fp); fclose(fp); printf("二進位讀取: "); for(int i=0; i<5; i++) printf("%d ", read_nums[i]); printf("\n"); return 0; }
⚙️
前置處理器
#define / #include / #ifdef / 巨集
CH.16
C — 前置處理器指令
#include <stdio.h> // 常數定義 #define PI 3.14159265358979 #define MAX_SIZE 100 #define BUFFER_SIZE 1024 // 函式型巨集 #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define SQUARE(x) ((x) * (x)) #define ABS(x) ((x) < 0 ? -(x) : (x)) // 條件編譯 #define DEBUG_MODE 1 #ifdef DEBUG_MODE #define DBG(msg) printf("[DEBUG] %s\n", msg) #else #define DBG(msg) #endif // 防止重複引入(Header Guard) #ifndef MYLIB_H #define MYLIB_H // ... 標頭內容 ... #endif int main() { printf("PI = %.10f\n", PI); printf("MAX(7,12) = %d\n", MAX(7, 12)); printf("SQUARE(5) = %d\n", SQUARE(5)); printf("ABS(-42) = %d\n", ABS(-42)); DBG("程式開始執行"); // 預定義巨集 printf("編譯時間: %s %s\n", __DATE__, __TIME__); printf("此行行號: %d\n", __LINE__); printf("此檔名: %s\n", __FILE__); return 0; }
🔢
位元運算
AND / OR / XOR / NOT / 位移
CH.17
運算子名稱說明範例結果
&AND兩位都為1才為10b1100 & 0b10100b1000 (8)
|OR有一個為1就為10b1100 | 0b10100b1110 (14)
^XOR不同才為10b1100 ^ 0b10100b0110 (6)
~NOT位元反轉~0b00000b1111...
<<左移乘以2的n次方1 << 38
>>右移除以2的n次方16 >> 24
C — 位元運算實用技巧
#include <stdio.h> int main() { unsigned int flags = 0b00000000; // 設定第 n 位元 (Set bit) flags |= (1 << 2); // 設定第2位 flags |= (1 << 5); // 設定第5位 printf("設定後: %d\n", flags); // 36 // 清除第 n 位元 (Clear bit) flags &= ~(1 << 2); printf("清除後: %d\n", flags); // 32 // 切換第 n 位元 (Toggle bit) flags ^= (1 << 5); printf("切換後: %d\n", flags); // 0 // 判斷奇偶(最快速的方法) int n = 42; printf("%d 是 %s\n", n, (n&1) ? "奇數":"偶數"); // 乘除 2 的次方(位移比乘除更快) printf("3 * 8 = %d (3 << 3)\n", 3 << 3); printf("64 / 4 = %d (64 >> 2)\n", 64 >> 2); // XOR 交換(不需暫存變數) int a = 100, b = 200; a ^= b; b ^= a; a ^= b; printf("XOR交換: a=%d b=%d\n", a, b); return 0; }
▶ 輸出結果
設定後: 36
清除後: 32
切換後: 0
42 是 偶數
3 * 8 = 24 (3 << 3)
64 / 4 = 16 (64 >> 2)
XOR交換: a=200 b=100
🎯
完整範例
實戰案例:排序、搜尋、鏈結串列
CH.18
C — 快速排序(QuickSort)
#include <stdio.h> void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } int partition(int arr[], int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] <= pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i+1], &arr[high]); return i + 1; } void quickSort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } int main() { int arr[] = {64,25,12,22,11,90,3,55}; int n = sizeof(arr)/sizeof(arr[0]); printf("排序前: "); for(int i=0; i<n; i++) printf("%d ", arr[i]); quickSort(arr, 0, n-1); printf("\n排序後: "); for(int i=0; i<n; i++) printf("%d ", arr[i]); printf("\n"); return 0; }
▶ 輸出結果
排序前: 64 25 12 22 11 90 3 55
排序後: 3 11 12 22 25 55 64 90
C — 鏈結串列(Linked List)
#include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node *next; } Node; Node* createNode(int val) { Node *n = (Node*)malloc(sizeof(Node)); n->data = val; n->next = NULL; return n; } void push(Node **head, int val) { Node *n = createNode(val); n->next = *head; *head = n; } void append(Node **head, int val) { Node *n = createNode(val); if (!*head) { *head = n; return; } Node *cur = *head; while (cur->next) cur = cur->next; cur->next = n; } void printList(Node *head) { while (head) { printf("%d", head->data); if(head->next) printf(" → "); head = head->next; } printf(" → NULL\n"); } int main() { Node *list = NULL; append(&list, 10); append(&list, 20); append(&list, 30); push(&list, 5); // 插入頭部 printList(list); return 0; }
▶ 輸出結果
5 → 10 → 20 → 30 → NULL
C — 堆疊實作(Stack)
#include <stdio.h> #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int top; } Stack; void init(Stack *s) { s->top = -1; } int isEmpty(Stack *s) { return s->top == -1; } int isFull(Stack *s) { return s->top == MAXSIZE-1; } void push(Stack *s, int val) { if (isFull(s)) { printf("堆疊已滿\n"); return; } s->data[++s->top] = val; printf("push(%d)\n", val); } int pop(Stack *s) { if (isEmpty(s)) { printf("堆疊為空\n"); return -1; } return s->data[s->top--]; } int peek(Stack *s) { return isEmpty(s) ? -1 : s->data[s->top]; } int main() { Stack s; init(&s); push(&s, 10); push(&s, 20); push(&s, 30); printf("頂端: %d\n", peek(&s)); printf("pop: %d\n", pop(&s)); printf("pop: %d\n", pop(&s)); return 0; }
▶ 輸出結果
push(10)
push(20)
push(30)
頂端: 30
pop: 30
pop: 20
C — 矩陣乘法
#include <stdio.h> #define N 3 void multiply(int A[N][N], int B[N][N], int C[N][N]) { for(int i=0; i<N; i++) for(int j=0; j<N; j++) { C[i][j] = 0; for(int k=0; k<N; k++) C[i][j] += A[i][k] * B[k][j]; } } void printMatrix(char *name, int M[N][N]) { printf("%s:\n", name); for(int i=0; i<N; i++) { for(int j=0; j<N; j++) printf("%4d", M[i][j]); printf("\n"); } } int main() { int A[N][N] = {{1,2,3},{4,5,6},{7,8,9}}; int B[N][N] = {{9,8,7},{6,5,4},{3,2,1}}; int C[N][N]; multiply(A, B, C); printMatrix("A", A); printMatrix("B", B); printMatrix("C = A×B", C); return 0; }
▶ 輸出結果
C = A×B:
30 24 18
84 69 54
138 114 90

🎯 C 語言互動測驗

測試你對 C 語言的了解程度!共 10 題

1/10 題
得分: 0
🎉

🚀 繼續深入學習

恭喜完成 C 語言基礎課程!接下來挑戰資料結構、演算法或 C++ 進階開發。

已複製到剪貼板!