C 语言基础知识复习资料目录数据类型与变量运算符与表达式控制结构数组与字符串函数指针 ⭐⭐⭐结构体与联合体文件操作内存管理 ⭐⭐⭐1. 数据类型与变量1.1 基本数据类型类型关键字大小说明整型int4 字节基本整型短整型short2 字节长整型long4/8 字节字符型char1 字节单精度浮点float4 字节双精度浮点double8 字节1.2 类型修饰符signed int a; // 有符号整型默认 unsigned int b; // 无符号整型 long int c; // 长整型 short int d; // 短整型1.3 变量声明与初始化int a; // 声明未初始化值为随机值 int b 10; // 声明并初始化 int c 0; // 显式初始化为 0 const int MAX 100; // 常量不可修改⚠️ 易错点未初始化的局部变量值是随机的垃圾值全局变量和静态变量默认初始化为 0const变量必须在声明时初始化1.4 例题例题 1下列哪个变量的值是不确定的int a; int b 0; static int c;答案a局部变量未初始化2. 运算符与表达式2.1 算术运算符 - * / % // 加减乘除取模⚠️ 易错点整数除法结果是整数5 / 2 2取模运算只能用于整数5 % 2 12.2 自增自减运算符int a 5; int b a; // b 5, a 6 (后置先使用后加) int c a; // a 7, c 7 (前置先加后使用)⚠️ 重点后置返回原值前置返回新值2.3 关系与逻辑运算符 ! // 关系运算符 ! || // 逻辑运算符2.4 位运算符 // 按位与 | // 按位或 ^ // 按位异或 ~ // 按位取反 // 左移 // 右移例题5 1的结果是答案10相当于 5 * 22.5 运算符优先级高到低() [] - . // 括号、数组、成员访问 ! ~ -- // 单目运算符 * / % // 乘除取模 - // 加减 // 移位 // 关系 ! // 相等 // 位与 ^ // 位异或 | // 位或 // 逻辑与 || // 逻辑或 ?: // 条件 - // 赋值3. 控制结构3.1 if-else 语句if (条件) { // 代码块 } else if (条件) { // 代码块 } else { // 代码块 }⚠️ 易错点判断相等用不是C 语言中 0 为假非 0 为真3.2 switch 语句switch (表达式) { case 常量 1: // 代码 break; case 常量 2: // 代码 break; default: // 默认代码 }⚠️ 易错点忘记写break会导致穿透继续执行下一个 casecase 后面必须是常量表达式3.3 循环语句// for 循环 for (初始化; 条件; 更新) { // 代码 } ​ // while 循环 while (条件) { // 代码 } ​ // do-while 循环至少执行一次 do { // 代码 } while (条件);3.4 break 和 continuebreak; // 跳出整个循环/switch continue; // 跳过本次循环进入下一次3.5 例题例题以下代码输出什么for (int i 0; i 5; i) { if (i 3) continue; printf(%d , i); }答案0 1 2 44. 数组与字符串4.1 一维数组int arr[5] {1, 2, 3, 4, 5}; // 初始化 int arr[5] {0}; // 全部初始化为 0 int arr[] {1, 2, 3}; // 自动推断大小为 3⚠️ 重点数组索引从 0 开始数组名是数组首元素的地址指针4.2 二维数组int matrix[3][4] { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };4.3 字符数组与字符串char str1[] hello; // 自动包含 \0长度为 6 char str2[6] hello; // 刚好容纳 char str3[] {h, e, l, l, o, \0}; // 手动添加结束符⚠️ 易错点字符串必须以\0结尾strlen()返回不包括\0的长度4.4 字符串操作函数#include string.h ​ strlen(str) // 字符串长度 strcpy(dest, src) // 字符串复制 strcat(str1, str2) // 字符串连接 strcmp(str1, str2) // 字符串比较返回 0 表示相等4.5 例题例题strlen(hello)和sizeof(hello)的结果分别是答案5和65. 函数5.1 函数定义与声明// 函数声明原型 int add(int a, int b); ​ // 函数定义 int add(int a, int b) { return a b; } ​ // 无返回值函数 void print(int n) { printf(%d, n); }5.2 参数传递C 语言只有值传递void swap_wrong(int a, int b) { int temp a; a b; b temp; // 不会改变实参 } ​ void swap_correct(int *a, int *b) { int temp *a; *a *b; *b temp; // 通过指针改变实参 }⭐⭐⭐ 重点要修改实参必须传递指针5.3 递归函数int factorial(int n) { if (n 1) return 1; // 终止条件 return n * factorial(n - 1); }⚠️ 易错点必须设置终止条件否则会栈溢出5.4 例题例题以下代码能否交换 a 和 b 的值void swap(int x, int y) { int t x; x y; y t; } int main() { int a 1, b 2; swap(a, b); return 0; }答案不能C 语言是值传递6. 指针 ⭐⭐⭐⭐⭐6.1 指针基础int a 10; int *p a; // p 指向 a 的地址 *p 20; // 通过指针修改 a 的值⭐⭐⭐ 重点取地址运算符*解引用运算符获取指针指向的值6.2 指针运算int arr[] {1, 2, 3, 4, 5}; int *p arr; ​ p; // 指向下一个元素移动 sizeof(int) 字节 p 2; // 指向 arr[2] *(p 3); // 等价于 arr[3]6.3 指针与数组int arr[5] {1, 2, 3, 4, 5}; ​ arr[i] *(arr i) // 等价 i[arr] arr[i] // 等价合法但不推荐6.4 多级指针int a 10; int *p a; int **pp p; ​ **pp 20; // 修改 a 的值为 206.5 空指针与野指针int *p NULL; // 空指针安全 int *p; // 野指针危险未初始化⚠️ 易错点使用指针前必须初始化释放内存后应将指针置为 NULL6.6 const 与指针const int *p1; // 指向常量的指针不能通过 p1 修改值 int *const p2; // 常量指针p2 不能指向其他地方 const int *const p3; // 指向常量的常量指针两者都不能6.7 函数指针int add(int a, int b) { return a b; } ​ int (*func_ptr)(int, int) add; // 声明函数指针 int result func_ptr(3, 4); // 调用6.8 例题例题以下代码输出什么int arr[] {1, 2, 3}; int *p arr; printf(%d, *(p));答案27. 结构体与联合体7.1 结构体struct Student { char name[20]; int age; float score; }; ​ // 定义结构体变量 struct Student s1 {张三, 20, 95.5}; ​ // 访问成员 s1.age 21; printf(%s, s1.name); ​ // 结构体指针 struct Student *p s1; p-age 22; // 等价于 (*p).age7.2 typedef 简化typedef struct { int x; int y; } Point; ​ Point p {1, 2}; // 不需要 struct 关键字7.3 联合体union Data { int i; float f; char c; }; ​ // 所有成员共享同一块内存 union Data d; d.i 10; d.f 3.14; // i 的值会被覆盖⭐⭐⭐ 重点联合体所有成员共享内存大小等于最大成员的大小7.4 例题例题以下结构体大小是多少struct { char a; int b; char c; };答案通常为 8 字节考虑内存对齐8. 文件操作8.1 基本操作#include stdio.h ​ // 打开文件 FILE *fp fopen(file.txt, r); // r: 读w: 写a: 追加 ​ // 读写操作 fscanf(fp, %d, n); fprintf(fp, %d, n); ​ // 关闭文件 fclose(fp);8.2 文件操作模式模式说明r只读打开w只写打开清空原文件a追加打开r读写打开w读写打开清空rb二进制读wb二进制写8.3 文件读写函数fgetc(fp); // 读取一个字符 fputc(c, fp); // 写入一个字符 fgets(str, n, fp); // 读取一行 fputs(str, fp); // 写入字符串 fread(buf, size, count, fp); // 二进制读 fwrite(buf, size, count, fp); // 二进制写8.4 文件位置操作fseek(fp, 0, SEEK_SET); // 移动到文件开头 fseek(fp, 0, SEEK_CUR); // 当前位置 fseek(fp, 0, SEEK_END); // 文件末尾 ftell(fp); // 获取当前位置 rewind(fp); // 回到文件开头8.5 例题例题以下代码有什么问题FILE *fp fopen(test.txt, w); fclose(fp);答案没有检查 fopen 是否成功返回 NULL9. 内存管理 ⭐⭐⭐⭐⭐9.1 动态内存分配#include stdlib.h // 分配内存 int *p (int *)malloc(sizeof(int)); // 分配 1 个 int int *arr (int *)malloc(10 * sizeof(int)); // 分配 10 个 int // 分配并初始化为 0 int *p (int *)calloc(10, sizeof(int)); // 10 个 int初始为 0 // 调整大小 p (int *)realloc(p, 20 * sizeof(int)); // 释放内存 free(p); p NULL; // 防止悬空指针9.2 内存分配函数对比函数说明初始化malloc(n)分配 n 字节不初始化calloc(n, s)分配 n 个 s 字节初始化为 0realloc(p, n)调整 p 的大小新部分不初始化free(p)释放内存-9.3 常见内存问题内存泄漏分配后未释放void leak() { int *p malloc(sizeof(int)); // 忘记 free(p) }重复释放free(p); free(p); // 错误悬空指针int *p malloc(sizeof(int)); free(p); *p 10; // 错误访问已释放内存⚠️ 重点每次malloc都要对应freefree后应将指针置为 NULL检查malloc返回值是否为 NULL9.4 存储类别auto int a 10; // 自动变量默认栈上 static int b 0; // 静态变量数据区保留值 extern int c; // 外部变量引用其他文件的变量 register int d; // 寄存器变量建议9.5 例题例题以下代码有什么问题int *get_array() { int arr[10]; return arr; // 返回局部数组地址 }答案返回了栈上局部变量的地址函数返回后内存已释放重点总结⭐⭐⭐⭐⭐ 必须掌握指针操作指针与数组、指针运算、函数指针内存管理malloc/free、内存泄漏、内存对齐结构体定义、访问、结构体指针⭐⭐⭐⭐ 重点掌握函数参数传递值传递、通过指针修改实参字符串操作字符串结束符、常用字符串函数文件操作文件打开模式、读写函数⭐⭐⭐ 常考易错自增自减前置与后置的区别const 修饰const 指针与指针 const联合体共享内存特性递归终止条件综合练习题练习 1指针与数组// 编写函数使用指针遍历数组并求和 int sum_array(int *arr, int size);练习 2结构体// 定义学生结构体包含姓名、学号、成绩 // 编写函数计算平均分练习 3链表// 创建单链表实现插入、删除、遍历操作练习 4文件操作// 读取文件内容并统计单词数量参考资源《C Primer Plus》《C 和指针》《C 陷阱与缺陷》《深入理解计算机系统》祝学习顺利