第一部分:C 语言基础
什么是 C 语言?
C 语言是一种高级语言,但它也提供了低级操作的能力(如直接内存访问),因此它常被称为“中级语言”,它由 Dennis Ritchie 于 1972 年在贝尔实验室发明,最初用于开发 Unix 操作系统。

(图片来源网络,侵删)
-
优点:
- 高效:运行速度快,接近汇编语言。
- 灵活:可以直接操作硬件,功能强大。
- 可移植:代码可以在不同平台(Windows, Linux, macOS)上轻松编译运行。
- 影响深远:是学习计算机科学和编程思想的基石。
-
缺点:
- 指针复杂:指针是 C 语言的精髓,但也是初学者的难点。
- 缺乏自动内存管理:需要手动分配和释放内存,容易导致内存泄漏或野指针。
- 缺乏现代语言特性:没有内置的面向对象、异常处理等。
你的第一个 C 程序:Hello, World!
这是所有编程语言学习的传统起点,它让我们了解一个 C 程序的基本结构。
#include <stdio.h> // 1. 预处理器指令
int main() { // 2. 主函数
printf("Hello, World!\n"); // 3. 函数调用
return 0; // 4. 返回值
}
代码解析:

(图片来源网络,侵删)
-
#include <stdio.h>:#include是预处理器指令。- 它告诉编译器在编译前将
stdio.h文件的内容包含进来。 stdio.h是标准输入输出库,包含了printf()函数的声明(告诉编译器这个函数存在以及如何使用它)。
-
int main():main是程序的主函数,C 程序的执行总是从main函数开始。int表示这个函数执行完毕后会返回一个整数值。return 0;表示程序成功执行完毕,操作系统会收到这个返回值。
-
printf("Hello, World!\n");:printf是一个库函数,用于在屏幕上打印文本。\n是一个转义字符,代表“换行”。- 分号 :在 C 语言中,每个语句都必须以分号结尾。
-
return 0;:
(图片来源网络,侵删)- 结束
main函数,并向操作系统返回0,表示程序正常退出。
- 结束
如何编译和运行 C 程序?
你需要一个编译器,最常用的是 GCC (GNU Compiler Collection)。
- 保存代码:将上面的代码保存为
hello.c。 - 打开终端/命令提示符。
- 编译:使用
gcc命令。gcc hello.c -o hello
gcc hello.c:告诉 GCC 编译hello.c文件。-o hello:指定输出的可执行文件名为hello(在 Windows 上是hello.exe)。
- 运行:
- Linux/macOS:
./hello
- Windows (CMD):
hello.exe
- Windows (PowerShell):
.\hello.exe
你将在终端看到输出:
Hello, World!
- Linux/macOS:
第二部分:核心语法
变量与数据类型
变量是存储数据的容器,C 语言是强类型语言,每个变量在使用前必须声明其类型。
| 数据类型 | 描述 | 示例 |
|---|---|---|
int |
整数 | 10, -50, 0 |
char |
单个字符 | 'a', 'Z', '1' |
float |
单精度浮点数(小数) | 14f, -0.5f |
double |
双精度浮点数(更高精度) | 1415926, -0.55 |
void |
无类型 | 用于函数返回值 |
示例:
#include <stdio.h>
int main() {
int age = 25;
char initial = 'J';
float pi = 3.14f;
double price = 19.99;
printf("Age: %d\n", age);
printf("Initial: %c\n", initial);
printf("Pi: %f\n", pi);
printf("Price: %lf\n", price); // %lf 用于 double
return 0;
}
格式化输出说明:
%d:用于打印整数 (int)。%c:用于打印字符 (char)。%f:用于打印浮点数 (float或double)。%lf:专门用于打印double类型(虽然%f也能用,但%lf更规范)。
常量与符号常量
常量是其值在程序运行期间不能改变的变量。
const关键字:const int MAX_STUDENTS = 30; // MAX_STUDENTS = 31; // 这行代码会编译错误!
#define预处理器指令(C 语言风格):#define PI 3.14159 // PI = 3.14; // 这行代码也会编译错误!
现代 C 语言更推荐使用
const。
运算符
- 算术运算符:, , , , (取模/求余)
- 关系运算符: (等于), (不等于),
>,<,>=,<= - 逻辑运算符:
&&(与), (或), (非) - 赋值运算符:, , , , (
a += 5等价于a = a + 5)
输入与输出
printf():格式化输出。scanf():格式化输入。极其重要:scanf需要变量的地址,而不是变量本身,地址通过&运算符获取。
示例:
#include <stdio.h>
int main() {
int number;
char name[50]; // 字符数组,用于存储字符串
printf("Enter an integer: ");
scanf("%d", &number); // 注意 &number
printf("Enter your name: ");
scanf("%s", name); // 字符数组名本身就是地址,不需要 &
printf("You entered: %d\n", number);
printf("Hello, %s\n", name);
return 0;
}
控制流
控制流语句决定了程序的执行顺序。
A. 条件语句
-
if-else:int score = 85; if (score >= 90) { printf("Grade: A\n"); } else if (score >= 80) { printf("Grade: B\n"); } else { printf("Grade: C or below\n"); } -
switch:char grade = 'B'; switch (grade) { case 'A': printf("Excellent!\n"); break; // 必须使用 break 来跳出 switch case 'B': printf("Good job!\n"); break; default: printf("Keep trying!\n"); }
B. 循环语句
for循环:适用于已知循环次数的场景。for (int i = 0; i < 5; i++) { printf("Iteration %d\n", i); }while循环:适用于循环次数不确定,依赖条件判断的场景。int count = 0; while (count < 5) { printf("Count is %d\n", count); count++; }do-while循环:至少执行一次循环体,然后再判断条件。int num = 1; do { printf("Num is %d\n", num); num++; } while (num <= 5);
第三部分:进阶核心概念
数组
数组是存储相同类型的多个元素的集合。
一维数组:
int numbers[5]; // 声明一个包含5个整数的数组 numbers[0] = 10; // 数组索引从0开始 numbers[1] = 20;
二维数组:
int matrix[3][4]; // 3行4列的二维数组 matrix[0][0] = 1;
函数
函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。
函数结构:
返回类型 函数名(参数列表) {
// 函数体
return 返回值; // 如果返回类型是 void,则可以省略
}
示例:
#include <stdio.h>
// 函数声明
int add(int a, int b);
int main() {
int sum = add(5, 3);
printf("Sum is: %d\n", sum); // 输出 Sum is: 8
return 0;
}
// 函数定义
int add(int a, int b) {
return a + b;
}
指针 (Pointers) - C 语言的精髓
指针是一个变量,它存储的是另一个变量的内存地址。
- 声明:
类型 *指针名; - 取地址:
&运算符 - 解引用: 运算符(获取地址中存储的值)
示例:
#include <stdio.h>
int main() {
int var = 10;
int *ptr; // 声明一个整型指针 ptr
ptr = &var; // 将 var 的地址赋给 ptr
printf("Value of var: %d\n", var); // 输出 10
printf("Address of var: %p\n", &var); // 输出 var 的内存地址
printf("Value of ptr: %p\n", ptr); // 输出 ptr 存储的地址(和 var 的地址一样)
printf("Value pointed by ptr: %d\n", *ptr); // 输出 ptr 指向的值(即 var 的值,10)
return 0;
}
指针的用途:
- 动态内存分配:在程序运行时分配内存。
- 高效传递数据:向函数传递大型结构体时,传递指针比传递整个数据结构更高效。
- 实现数据结构:链表、树、图等复杂数据结构都依赖指针。
结构体 (Structures)
结构体允许你将不同类型的变量组合成一个单一的、自定义的类型。
#include <stdio.h>
#include <string.h>
// 定义一个结构体类型
struct Student {
int id;
char name[50];
float gpa;
};
int main() {
// 声明一个结构体变量
struct Student student1;
// 访问和赋值成员
student1.id = 101;
strcpy(student1.name, "Alice"); // 使用 strcpy 函数复制字符串
student1.gpa = 3.8;
printf("Student ID: %d\n", student1.id);
printf("Student Name: %s\n", student1.name);
printf("Student GPA: %.2f\n", student1.gpa);
return 0;
}
第四部分:C 语言编程实践建议
- 动手敲代码:不要只看,一定要自己写,从模仿开始,然后尝试修改和创造。
- 学会使用调试器:学习使用 GDB (Linux/macOS) 或 Visual Studio Debugger (Windows) 来单步执行代码、查看变量值,这比
printf调试更强大。 - 阅读优秀代码:阅读开源项目(如 SQLite, Redis)的源码,学习大师是如何组织代码和解决问题的。
- 理解内存模型:深入理解栈、堆、静态/全局内存区的区别,这是理解指针和内存管理的关键。
- 善用工具:
- IDE:Visual Studio (Windows), CLion (跨平台), VS Code + C/C++ 插件。
- 编译器:GCC, Clang。
- 构建工具:Make, CMake (大型项目必备)。
C 语言虽然古老,但其设计哲学和核心概念(如指针、内存管理)至今仍是衡量一个程序员功底的重要标准,学习 C 语言不仅能让你掌握一门强大的工具,更能让你深刻理解计算机是如何工作的。
这份指南为你勾勒了 C 语言的全景图,下一步,就是选择一个主题,深入下去,不断练习,享受编程的乐趣!
