1. 引言
C 语言作为计算机科学领域的基石,至今仍是系统开发、嵌入式编程、操作系统实现等领域的核心语言。无论是学习数据结构、算法,还是深入理解计算机底层原理,C 语言都是绕不开的重要工具。本文将从基础语法到高级特性,系统性地总结 C 语言的核心知识点,帮助读者建立完整的知识框架。
2. 基础语法与数据类型
2.1 基本数据类型
C 语言提供了丰富的数据类型,主要包括:
- 整型 :
int、short、long、long long,以及对应的无符号类型(unsigned) - 浮点型 :
float(单精度)、double(双精度)、long double(扩展精度) - 字符型 :
char,用于存储单个字符,本质上是 1 字节的整型 - 布尔类型 :C99 标准引入
_Bool,通过<stdbool.h>可使用bool、true、false
2.2 变量与常量
变量声明格式为 类型 变量名;,例如:
c
int age = 20;
double salary = 8500.50;
char grade = 'A';
常量使用 const 关键字修饰,或在预处理阶段使用 #define 定义:
c
const double PI = 3.14159;
#define MAX_SIZE 100
2.3 运算符
C 语言的运算符可分为以下几类:
- 算术运算符 :
+、-、*、/、% - 关系运算符 :
>、<、>=、<=、==、!= - 逻辑运算符 :
&&(与)、||(或)、!(非) - 位运算符 :
&、|、^、~、<<、>> - 赋值运算符 :
=、+=、-=、*=、/=等 - 其他 :
sizeof、&(取地址)、*(解引用)、三元运算符?:
3. 流程控制
3.1 条件语句
c
if (score >= 90) {
printf("优秀\n");
} else if (score >= 60) {
printf("及格\n");
} else {
printf("不及格\n");
}
switch 语句适用于多分支定值判断:
c
switch (day) {
case 1: printf("星期一\n"); break;
case 2: printf("星期二\n"); break;
default: printf("无效输入\n"); break;
}
3.2 循环语句
C 语言提供三种循环结构:
c
// for 循环
for (int i = 0; i < 10; i++) {
printf("%d ", i);
}
// while 循环
int j = 0;
while (j < 10) {
printf("%d ", j);
j++;
}
// do-while 循环(至少执行一次)
int k = 0;
do {
printf("%d ", k);
k++;
} while (k < 10);
4. 函数
4.1 函数定义与调用
函数是 C 语言模块化编程的基础:
c
// 函数声明
int add(int a, int b);
// 函数定义
int add(int a, int b) {
return a + b;
}
// 函数调用
int result = add(3, 5);
4.2 参数传递
C 语言默认采用值传递,函数内对形参的修改不会影响实参。若需修改实参,必须传递指针:
c
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
// 调用
int a = 10, b = 20;
swap(&a, &b); // 此时 a=20, b=10
4.3 递归
递归是函数调用自身的编程技巧,经典示例为阶乘计算:
c
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
5. 数组与字符串
5.1 一维数组
c
int scores[5] = {85, 90, 78, 92, 88};
// 遍历
for (int i = 0; i < 5; i++) {
printf("%d ", scores[i]);
}
5.2 二维数组
c
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
5.3 字符串
C 语言中字符串本质上是字符数组,以 \0 结尾:
c
char str1[] = "Hello";
char str2[20];
strcpy(str2, str1); // 字符串拷贝
int len = strlen(str1); // 字符串长度
strcat(str2, " World"); // 字符串拼接
6. 指针
6.1 指针基础
指针是 C 语言的精髓,用于存储变量的内存地址:
c
int num = 10;
int *ptr = # // ptr 指向 num 的地址
printf("%d\n", *ptr); // 解引用,输出 10
6.2 指针与数组
数组名本质上是指向首元素的常量指针:
c
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 等价于 int *p = &arr[0];
printf("%d\n", *(p + 2)); // 输出 3
6.3 指针与函数
函数指针可以像变量一样传递和调用:
c
int add(int a, int b) { return a + b; }
int (*funcPtr)(int, int) = add;
int result = funcPtr(3, 4); // 输出 7
6.4 动态内存分配
c
int *arr = (int *)malloc(10 * sizeof(int));
if (arr == NULL) {
printf("内存分配失败\n");
return -1;
}
// 使用完毕后释放内存
free(arr);
7. 结构体与联合体
7.1 结构体
结构体用于组合不同类型的数据:
c
struct Student {
char name[50];
int age;
double score;
};
struct Student stu = {"张三", 20, 89.5};
printf("%s 的年龄是 %d\n", stu.name, stu.age);
7.2 结构体指针
c
struct Student *pStu = &stu;
printf("%s\n", pStu->name); // 使用 -> 访问成员
7.3 联合体
联合体所有成员共享同一块内存,同一时刻只能存储一个成员的值:
c
union Data {
int i;
float f;
char str[20];
};
8. 文件操作
8.1 文件打开与关闭
c
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
printf("文件打开失败\n");
return -1;
}
// 文件操作...
fclose(fp);
8.2 文件读写
c
// 写入文件
FILE *fp = fopen("output.txt", "w");
fprintf(fp, "Hello, C Language!\n");
fclose(fp);
// 读取文件
fp = fopen("output.txt", "r");
char buffer[100];
while (fgets(buffer, 100, fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
9. 预处理指令
9.1 宏定义
c
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
9.2 条件编译
c
#ifdef DEBUG
printf("调试模式\n");
#else
printf("发布模式\n");
#endif
9.3 头文件包含
c
#include <stdio.h> // 标准库头文件
#include "myheader.h" // 自定义头文件
10. 常见易错点与最佳实践
10.1 常见错误
- 数组越界:C 语言不检查数组边界,越界访问可能导致程序崩溃或数据损坏
- 空指针解引用:使用指针前必须确认非空
- 内存泄漏:动态分配的内存必须及时释放
- 字符串未以
\0结尾:可能导致缓冲区溢出 - 整数溢出:注意数据类型的取值范围
10.2 最佳实践
- 变量命名使用有意义的名称,遵循命名规范
- 每个函数只做一件事,保持函数短小精悍
- 使用
const修饰不会被修改的参数 - 动态内存分配后立即检查返回值
- 释放内存后将指针置为
NULL,避免野指针 - 编写清晰的注释,说明代码意图
11. 总结
C 语言是一门简洁而强大的编程语言,掌握它需要理解指针、内存管理等核心概念。本文从基础语法、流程控制、函数、数组、指针、结构体、文件操作到预处理指令,系统梳理了 C 语言的核心知识体系。建议读者在理论学习的基础上,多动手编写代码、调试程序,通过实践加深理解。C 语言的学习是一个循序渐进的过程,打好基础后,无论是深入系统编程、嵌入式开发,还是转向 C++、Java 等高级语言,都将事半功倍。