C语言期末复习笔记

C语言期末备考突击复习笔记

这份笔记包括了C语言基础学习的一些难点,而不是从基本语法开始写起,

1. 数组与指针

核心概念

  1. 数组名 = 首地址

    • int a[5];a 的值等于 &a[0]
    • 区别:在 Java 中数组是对象,在 C 中数组是连续内存块。
  2. 指针运算(跳格子)

    • 指针加减不是简单的数学加减,而是基于数据类型的大小(步长)

    • 假设地址为 1000:

c 复制代码
     int *p = (int*)1000;
     p + 1; // 结果是 1004 (跳过 4 字节)
     
     double *d = (double*)1000;
     d + 1; // 结果是 1008 (跳过 8 字节)
  1. 二维数组内存布局

    • 二维数组(如 int a[2][3])在内存中是**连续"拉直"**存储的(行主序)。
    • a[0][2] 的下一个元素紧挨着 a[1][0]

⚠️ 高频易错点:指针声明

  • 指针数组 (Array of Pointers): int *p[10];
    • [] 优先级高,先结合。本质是数组,里面存了 10 个指针。
  • 数组指针 (Pointer to Array): int (*p)[10];
    • () 强制结合。本质是指针,指向一个长度为 10 的数组。
    • 场景:用于指向二维数组的一行。

2. 字符串

核心概念

  • 没有 String 类型 :C 语言用字符数组 char[] 模拟字符串。
  • 结束标记 :必须以 \0 结尾。"Hi" 实际占用 3 字节 ('H', 'i', '\0')。

⚠️ 陷阱:只读 vs 可写C

c 复制代码
// 1. 字符数组 (栈内存) ->  可以修改
char s[] = "Hello";
s[0] = 'X'; // 变成 "Xello"

// 2. 字符串字面量指针 (常量区) ->  禁止修改 (崩溃)
char *p = "Hello";
p[0] = 'X'; // Segmentation Fault!

⚠️ 陷阱:输入读取

  • scanf("%s", s): 遇到空格就停止。输入 "Hello World" -> 只读入 "Hello"。
  • fgets(s, size, stdin): 可以读取带空格的整行。

3. 函数

核心概念

  1. 值传递 (Pass by Value)

    • 默认情况下,函数参数传递的是复印件。修改形参不会影响实参。
  2. 传址调用 (Pass by Reference)

    • 想修改外面的变量,必须传地址
c 复制代码
   // ✅ 标准交换函数
   void swap(int *x, int *y) {
       int temp = *x; // 1. 取出 x 指向的值
       *x = *y;       // 2. 修改 x 指向的内存
       *y = temp;     // 3. 修改 y 指向的内存
   }
   // 调用:swap(&a, &b);

C⚠️ 致命错误:悬空指针

  • 绝对禁止返回局部变量的地址。
c 复制代码
  int* error_func() {
      int a = 10;
      return &a; // ❌ 函数结束 a 就被销毁了,返回的地址是废的
  }

静态变量

  • static int x = 0;: 记忆力超强。函数结束不销毁,下次调用保留上次的值。

4. 结构体

核心概念

  • 定义与大小
c 复制代码
  struct Student {
      char name[20]; // 20字节
      int age;       // 4字节
  };
  // sizeof(struct Student) 至少 24 字节
  • 成员访问

    • 变量访问:stu.age (点号)
    • 指针访问:p->age (箭头),等价于 (*p).age
  • 字符串赋值

    • ❌ 错误:stu.name = "Tom"; (数组名是常量)
    • ✅ 正确:strcpy(stu.name, "Tom"); (需要 <string.h>)

5. 链表

这是 C 语言最灵活的数据结构,也是考试大题热门。

5.1 结点的定义

c 复制代码
struct Node {
    int data;           // 数据域
    struct Node* next;  // 指针域:指向下一个同类结点
};

5.2 创建头结点

c 复制代码
struct Node* head = (struct Node*)malloc(sizeof(struct Node)); // 申请内存
head->next = NULL; // 初始为空链表,指向 NULL

5.3 遍历/输出链表

c 复制代码
void print_list(struct Node* head) {
    struct Node* p = head->next; // 假设带头结点,从第一个真数据开始
    // 如果是不带头结点的链表,就写 p = head;

    while (p != NULL) {          // 只要 p 指向的地方有房子
        printf("%d -> ", p->data);
        p = p->next;             // 关键动作:移动指针到下一格
    }
    printf("NULL\n");
}

5.4 插入结点

场景:把 newNode 插到 p 结点的后面。

口诀:先连后,再连前(防止断链)。

c 复制代码
// 1. 新结点的右手先拉住后面的人 (B)
newNode->next = p->next;

// 2. p 的右手松开 B,改去拉住新结点
p->next = newNode;

5.5 删除结点

场景:删除 p 后面的那个结点(假设叫 target)。

口诀:先备份,再过河拆桥,最后清理门户。

c 复制代码
// 1. 备份:先找到要删的目标,记下来
struct Node* target = p->next;

// 2. 拆桥:让 p 直接跳过 target,连上 target 的下一个人
p->next = target->next;

// 3. 释放:把 target 占用的内存还给系统 (防止内存泄漏)
free(target);

6. 共用体 & 枚举

  • 共用体 (union) :
    • 所有成员共用同一块地盘(省空间)。
    • 陷阱 :写了 u.f (float),之前的 u.i (int) 就被覆盖成乱码了。
  • 枚举 (enum) :
    • enum Color { RED, GREEN, BLUE };
    • 本质是整数常量:RED=0, GREEN=1, BLUE=2。提高代码可读性。

7. 文件操作

操作三部曲

  1. 打开 : FILE *fp = fopen("文件名", "模式"); if (fp == NULL) return; // 必须检查打开是否成功
  2. 读写 : fprintf, fscanf
  3. 关闭 : fclose(fp); (必做!)

打开模式

  • "r" (Read): 只读。文件不存在则报错 (NULL)。
  • "w" (Write): 只写 。文件存在则清空覆盖;不存在则创建。
  • "a" (Append): 追加。在文件末尾写,不覆盖原内容。

常用函数

c 复制代码
// 写入文本到文件
fprintf(fp, "Name: %s, Age: %d\n", name, age);

// 从文件读取数据
fscanf(fp, "%s %d", buffer_name, &buffer_age);
相关推荐
adsadswee2 小时前
Qt 样式与 QLinearGradient 渐变详解
开发语言·qt·qt样式表·qlineargradient·qss渐变效果
CoderYanger2 小时前
动态规划算法-01背包问题:50.分割等和子集
java·算法·leetcode·动态规划·1024程序员节
花月C2 小时前
个性化推荐:基于用户的协同过滤算法
开发语言·后端·算法·近邻算法
脾气有点小暴2 小时前
前端页面跳转的核心区别与实战指南
开发语言·前端·javascript
2401_834517073 小时前
AD学习笔记-27 泪滴的添加和移除
笔记·学习
rit84324993 小时前
基于MATLAB的BP神经网络手写数字识别
开发语言·神经网络·matlab
测试人社区-千羽3 小时前
大语言模型在软件测试中的应用与挑战
人工智能·测试工具·语言模型·自然语言处理·面试·职场和发展·aigc
zyq~3 小时前
【课堂笔记】凸优化问题-2
笔记
San30.3 小时前
深入 JavaScript 内存机制:从栈与堆到闭包的底层原理
开发语言·javascript·udp