lass="site-nav"> MJMJ 教学门户
本页定位 · C Language

C 语言是所有高级语言的祖宗。Linux、macOS、Windows、MySQL、Redis、Python 解释器本体,全是 C 写的。它不藏着掖着,把内存、指针、编译过程全摊开给你看——学完 C,你才算真的"看得见计算机在干活"。本页以 C11 为基线,顺带讲 C23(2023 年最新标准)的新东西,编译器要求 GCC 14+ / Clang 18+。

为
第 1 节 · 为什么学 C,以及把环境搭起来
Why C · Setup · Hello World · Build Pipeline

Why C · Setup · Hello World · Build Pipeline

进入本节 →
基
第 2 节 · 基础语法:变量、运算符、流程控制
Types · Operators · Control Flow

Types · Operators · Control Flow

进入本节 →
数
第 3 节 · 数组与字符串:C 里没有 string 类型
Arrays · Strings (char[])

Arrays · Strings (char[])

进入本节 →
指
第 4 节 · 指针:C 的灵魂,也是新手的鬼门关
Pointers — The Soul of C

Pointers — The Soul of C

进入本节 →
函
第 5 节 · 函数:把活儿打包,自己调自己也行
Functions · Recursion · Storage Classes

Functions · Recursion · Storage Classes

进入本节 →
结
第 6 节 · 结构体、共用体、枚举、typedef
struct · union · enum · typedef

struct · union · enum · typedef

进入本节 →
内
第 7 节 · 内存管理:C 程序员的成人礼
Memory Layout · malloc / free

Memory Layout · malloc / free

进入本节 →
文
第 8 节 · 文件 IO:让数据活过程序这次运行
File I/O with FILE*

File I/O with FILE*

进入本节 →
预
第 9 节 · 预处理与宏:编译前的文字替换
Preprocessor · #define · #include

Preprocessor · #define · #include

进入本节 →
位
第 10 节 · 位运算:直接掰扯二进制
Bitwise Operations

Bitwise Operations

进入本节 →
数
第 11 节 · 数据结构实战:用 C 手撸一遍
Linked List · Stack · Queue · Tree

Linked List · Stack · Queue · Tree

进入本节 →
小
第 12 节 · 小项目:学生成绩管理系统
Mini Project — Grade Manager

Mini Project — Grade Manager

进入本节 →
工
第 13 节 · 工具链实战:Makefile、gdb、valgrind
Makefile · gdb · valgrind

Makefile · gdb · valgrind

进入本节 →
常
第 14 节 · 常见坑与最佳实践
Pitfalls & Best Practices

Pitfalls & Best Practices

进入本节 →
构
第 15 节 · 构建系统:Make 与 CMake
Makefile · CMake · CMakeLists · targets & linking

Makefile · CMake · CMakeLists · targets & linking

进入本节 →
未
第 16 节 · 未定义行为与 Sanitizers
Undefined Behavior · ASan · UBSan · TSan · Valgrind

Undefined Behavior · ASan · UBSan · TSan · Valgrind

进入本节 →
结

小结与自测

Recap & Quiz

这一页从 Hello World 讲到手撸链表,核心就一句话:C 把内存摊开给你看,你学会了自己管它。指针和内存管理是分水岭,过了这两关,C 就算入门了。下面 5 道自测题,点开 details 对答案,错了就回翻对应章节。

自测 · C 语言

1.(指针题)下面代码运行后,x 的值是多少?

int x = 10; int *p = &x; *p = 20; printf("%d", x);
查看答案

答案:20。p 存的是 x 的地址,*p = 20 就是"按这个门牌号进去,把里面改成 20",改的就是 x 本身。解析:这正是指针能"改外面变量"的原理。

2.(内存题)为什么说 malloc 和 free 必须配对?只 malloc 不 free 会造成什么后果?

查看答案

答案:malloc 是向堆申请内存,free 是把内存还给系统。只申请不归还,就是内存泄漏——程序每跑一次就占着一块内存不撒手,跑久了可用内存越来越少,最终被系统杀掉。解析:C 没有垃圾回收,借了就得自己还。

3.(字符串题)char s[5] = "hello"; 这行为什么有问题?

查看答案

答案:"hello" 是 5 个可见字符,但 C 字符串末尾还要一个 '\0' 结束符,实际需要 6 个字节。数组只有 5 格,'\0' 被挤出去了。后果:printf/strlen 读到 s 后会继续往内存里乱读。正解:写成 char s[6] = "hello"; 或直接 char s[] = "hello";(编译器自动算 6)。

4.(编译题)编译一个 C 程序有哪四个阶段?报 undefined reference to 'xxx' 是在哪个阶段?

查看答案

答案:预处理 → 编译 → 汇编 → 链接。解析:undefined reference(未定义的引用)是链接阶段报的——你调用了某个函数,但找不到它的实现(库没链上、函数忘了写、拼写错)。它不是语法错,所以前面阶段都通过了,最后拼接时才发现"缺零件"。

5.(思维题)C 函数传参是"值传递",那为什么 swap 函数传 &a, &b 就能真正交换外面的变量?

查看答案

答案:传进去的虽然还是"副本",但这个副本装的是地址。swap 里通过 *a、*b 解引用,操作的是地址指向的那块真实内存,所以外面的 a、b 被改了。解析:值传递本身没变,变的是"传的是门牌号的副本"——拿着副本门牌号,照样能进那间房。

下一步往哪走

路学完 C 之后

① 想往系统/底层:接着学 C++(下一页)或直接读 Linux 源码、写个简单 shell。

② 想往应用开发:C 打底后转 Python/Go 会非常快——你会比别人多懂一层"为什么这样设计"。

③ C23 新东西:有空翻翻 nullptr、constexpr、#embed,但它们不是入门门槛,先用熟 C11 再说。