my-love-for-tomorrow

导航

期末C语言理论复习

第一部分C语言概述

  1. C语言的构成(函数),必须含有一个main函数。
  2. 执行顺序,从main开始,再min结束。
    预处理(进行基本替换#)->编译(检查语法,翻译为汇编语言)->汇编(翻译成二进制机器语言)->链接(调用不同库)
  3. 低级语言
    定义:直接贴近计算机硬件架构的语言,几乎不做抽象,分为两类:
    机器语言:纯二进制指令(0 和 1),是计算机能直接执行的语言;
    汇编语言:机器语言的 “符号化”(用助记符代替二进制,如MOV、ADD),需汇编器转换为机器语言。
    核心特点:执行效率极高(直接操作硬件),但可读性、可移植性、编程效率极差(需精通硬件架构,代码不通用)。
  4. 高级语言
    定义:贴近人类自然语言和逻辑思维的语言,对硬件细节做了抽象,独立于具体硬件架构。
    常见举例:C、C++、Java、Python、JavaScript 等(C 语言是其中的特殊存在)。
    核心特点:可读性、可移植性、编程效率好(不用关注硬件细节,代码跨平台),但需要编译 / 解释为机器语言才能执行,执行效率略低于低级语言。
  5. 算法特性
    0个或多个输入,一个或多个输出。
  6. 算法描述
    自然语言文字,流程图,伪代码,源程序。
  7. 常见缺点
    语法检查不严格,不检查数组越界,二义性

第二部分基本语法

1. 基本变量,数据类型

  1. 标识符(变量,常量,函数,数组...)命名规则 : 以下划线或者字符开头,只能出现数字,字母,下划线,大小写敏感,不能用关键字

  2. 基本数据类型(内存,存储方式,可执行操作)
    基本数据类型 :int char float double long short
    字节 :4--1--4--8--4--2
    常量 : 整型常量,浮点型常量,字符常量,字符串常量,符号常量。
    变量 :与上面类似
    注意 double a = 3 / 2 ; a的结果是 1,但是如果是3.0/2 就是1.5了
    八进制:0开头
    十六进制:0x开头
    数字后面加l或者L,代表长整型常量,.前后有0在不改变大小的情况下可以省略。
    科学计数法 e(E)的前后必须有数字,前面可以是小数,后面必须时整数。只能用于浮点数!属于浮点类型

  3. 构造类型 : struct union
    struct
    每一个成员变量都占用内存。
    union
    所有成员共享同一块内存空间, union 的总大小 = 其最大成员的大小(需满足内存对齐规则),而非成员大小之和(struct 是求和)。
    修改任意一个成员的值,会覆盖其他所有成员的值(因为内存共享),同一时间只能有效访问一个成员,多成员同时赋值无实际意义。

  4. 指针类型,空类型,定义类型

2. 分支语句

if语句

常与else同时出现,else与其上面最近的未与else配对的if进行配对,注意没有严格缩进,容易错,注意嵌套

switch语句

一般都会与case, break,default进行连用,注意是一般,switch和case后的表达式可以是整型表达式,或者字符型表达式
每一个case最后一般会有break,否则则会从第一个满足条件的选项开始执行,一直贯穿到最后。

3. 循环语句

while语句

执行顺序 : 判断条件-> 执行循环体, 注意与 do...while的区别即可,do...while一定会执行一次。
注意有无花括号,没有花括号只执行后面一句,同时注意分号位置
同时,写程序时别忘了更新判断条件。

for语句

执行顺序 : 表达式1(初始化) -> 表达式2(是否执行循环体的判断)-> 循环体 -> 条件3 -> 条件2
注意事项和while一样

break,continue语句

break结束当前循环,continue跳过本次进行下一次循环。都只针对其语句外的第一层循环语句,也只能干扰一层

3. 运算符优先级

  1. 位运算优先级核心位置:移位(<<、>>)在算术加减后、关系运算符前;按位与 / 异或 / 或在关系运算符后、逻辑与前,且 &>^>|;
  2. 整体优先级排序(高频):括号 > 单目 > 算术(乘除 > 加减) > 移位 > 关系 > 位运算(&>^>|) > 逻辑(&&>||) > 赋值 > 逗号;
  3. 易错点:区分位运算与算术、逻辑运算符的优先级,复杂表达式加括号规避错误.
  4. 易错结合性:单目、赋值运算符自右向左,其余高频运算符自左向右;

第三部分指针

一、指针基础(所有指针考点的核心铺垫)

指针的本质是存储内存地址的变量,定义格式为「数据类型 * 指针变量名」:
*指针名 表示取指针指向的内存值(解引用);
&变量名 表示取普通变量的内存地址;
核心规则:指针的 “数据类型” 必须与指向的变量类型匹配(如int *p只能指向int类型变量)。

二、多级指针(低频但易错)

定义逻辑:*的个数 = 指针层级,n 级指针专门存储 n-1 级指针的地址:
一级指针(int *p):存储int变量的地址;
二级指针(int **pp):存储一级指针p的地址;
三级指针(int **ppp):存储二级指针pp的地址。
核心易错:n 级指针需匹配 n 个&(取地址)或 n 个*(解引用),比如pp = &p(正确),int *
pp = &a(错误,a是普通 int 变量,需先定义int *p=&a再赋值)。

三、指针数组 vs 数组指针(考试高频核心区分)

  1. 指针数组(本质是 “数组”,元素是指针)
    定义:数据类型 *数组名[长度](如int *arr[5]);
    优先级逻辑:[]优先级高于*,arr先和[]结合成数组,再和*结合表示 “数组的每个元素都是 int 类型指针”;
    核心:占用内存 = 数组长度 × 指针大小(通常 4/8 字节),比如arr[0]是一个指向 int 变量的指针。
  2. 数组指针(本质是 “指针”,指向整个数组)
    定义:数据类型 (*指针名)[长度](如int (*p)[5]);
    优先级逻辑:()提升*的优先级,p先和*结合成指针,再和[]结合表示 “指针指向长度为 5 的 int 数组”;
    核心:仅占用一个指针的内存(4/8 字节),专门指向整个数组,而非单个元素。
    核心区分口诀:
    有括号先看指针(数组指针),无括号先看数组(指针数组)。

四、函数指针(指向函数的指针)

定义格式:返回值类型 (*指针名)(参数类型列表)(如int (*fp)(int, int));
优先级逻辑:()提升*优先级,fp先和*结合成指针,再和后面的()结合表示 “指针指向有 2 个 int 参数、返回 int 的函数”;
核心用法:函数名本身就是函数的入口地址,比如fp = add(add是int add(int a,int b)函数),调用(fp)(1,2)等价于add(1,2)。
易错点:函数指针的返回值、参数类型 / 个数必须与指向的函数完全匹配(如int (
fp)(int)不能指向void add(int, int))。

五、二维数组的行列区分 & 指针关联易错点

  1. 二维数组行列本质
    定义:数据类型 数组名[行数][列数](如int arr[3][4]);
    核心逻辑:二维数组是 “一维数组的数组”——arr包含 3 个元素(对应 3 行),每个元素又是包含 4 个 int 的一维数组(对应 4 列);
    行列区分:第一个[]是行,第二个[]是列(下标从 0 开始),比如arr[1][2]表示第 2 行、第 3 列的元素。
  2. 二维数组与指针的易错关联
    arr:指向 “第 0 行一维数组” 的数组指针(类型为int (*)[4]),不是一级指针,不能直接赋值给int *p;
    arr[i]:第 i 行的一维数组名,等价于&arr[i][0](第 i 行第 0 列元素的地址,一级指针);
    易错:混淆行 / 列下标(如arr[4][3]超出int arr[3][4]的范围)、将arr直接当作一级指针使用。

六、全模块高频易错点(考试必记)

  1. 优先级易错:[]/()优先级高于*,无括号时先结合[]/()(如int *p[5]是指针数组,不是数组指针);
  2. 类型匹配易错:多级指针、函数指针、数组指针的类型必须严格匹配(如二级指针不能直接指向普通变量);
  3. 二维数组下标易错:行 / 列下标从 0 开始,且行数 / 列数不能越界;
  4. 指针本质易错:数组指针、函数指针的核心是 “指针”(仅占一个指针内存),指针数组的核心是 “数组”(占数组总长度内存)。

总结

  1. 指针区分核心:看优先级(()提升*优先级)+ 本质(数组 / 指针),指针数组是 “数组存指针”,数组指针是 “指针指数组”;
  2. 多级指针:的个数 = 层级,需匹配对应个数的&/
  3. 二维数组:行在前列在后,arr是数组指针(指向行),arr[i]是一级指针(指向列元素);
  4. 函数指针:格式为 “返回值 (* 名)(参数)”,参数列表需与指向函数完全匹配。

第四部分输入输出

scanf()

这个比较基础,不要忘记有一个参数是地址就好。
读取字符串,遇到空格 / 换行 / 制表符停止,自动加'\0'。
%s 输入字符串 %c 输入字符 %d 整数 %lld 长整型注意用 %s %c 的时候,要额外处理末尾'\n'
两种处理办法 : 1.在%c 前加空格,也就是' %c',这样可以自动处理换行。2. 再多输入一次,把\n给吞掉就好

getchar()

字符的输入,一个一个输入,要处理换行符

gets()

读取一行,到换行符结束,自动丢弃换行符,再末尾添加\0

fgets(str, size, stdin)

整行输入,读取\n并存入字符串末尾

puts()

puts()核心功能是输出字符串,自动加换行,仅支持字符串输出

putchar()

putchar(ch):无格式控制,直接输出单个字符(可传字符 / ASCII 码),效率高于 printf

printf()

printf("%c", ch):灵活度高,可搭配其他格式输出单个字符。

  1. %d:输出十进制整数(int 类型);
  2. %f:输出浮点型(float/double,默认保留 6 位小数);
  3. %c:输出单个字符;
  4. %s:输出字符串(遇到'\0'停止);
  5. %x/%X:输出十六进制整数(小写 / 大写);
  6. %o:输出八进制整数;
  7. %p:输出指针地址(十六进制格式);
  8. %%:输出百分号本身(避免被解析为格式符)。
  9. 常用修饰符(高频易错
    宽度控制:%nd(n 为数字),输出整数占 n 个字符宽度,右对齐,不足补空格(如%5d输出 12,显示 “12”);
    左对齐:%-nd(加-),如%-5d输出 12,显示 “12”;
    小数位数:%.mf(m 为数字),控制浮点型小数位数(如%.2f输出 3.1415,显示 3.14);
    宽度 + 小数:%n.mf,如%8.2f输出 3.1415,显示 “3.14”(总宽度 8,2 位小数);
    补 0 填充:%0nd,不足宽度补 0(如%05d输出 12,显示 “00012”)。

转义字符

  1. \n:换行符(最高频)
    作用:输出后光标跳转到下一行开头;
    易错:区分\n(换行)和\r(回车,光标回到本行开头,考试低频,仅作了解)。
  2. \t:制表符(高频)
    作用:跳转到下一个 8 字符制表位实现对齐,非固定补 8 个空格(如前内容占 3 字符,\t补 5 个空格)。
  3. \\:反斜杠本身
    作用:输出\(直接写\会被解析为转义开头,导致语法错误);
    易错:输出文件路径时漏写第二个\(如C:\test应写C:\test)。
  4. \':单引号
    作用:输出单引号(单引号是字符常量定界符,直接写'会与语法冲突)。
  5. \":双引号
    作用:输出双引号(双引号是字符串定界符,直接写"会导致字符串语法错误);
    易错:字符串中直接写"(如printf("hello "world"");),必报错。
  6. \0:字符串结束符(隐性高频)
    作用:标记字符串结束,printf("%s")遇到\0立即停止输出;
    易错:字符数组未手动加\0,printf会越界读取,输出乱码。

第五部分常用库函数

qsort()

一、核心前提(考试必记)

qsort()是 C 标准库的通用快速排序函数,支持任意数据类型(int、char、结构体、字符串等)排序,需包含头文件 #include <stdlib.h>,否则编译报错。

二、函数原型与参数解析(考试高频)

qsort原型:void qsort(void base, size_t nitems, size_t size, int (compar)(const void , const void ));
逐个拆解核心参数(必考):
base:待排序数组的首地址(直接传数组名即可),void
表示通用类型,适配任意数组;
nitems:数组元素的总个数,size_t是无符号整型(输出需用%zu格式,而非%d,易错);
size:数组中单个元素的字节大小,必须用sizeof(元素类型)获取(如排序 int 数组传sizeof(int));
compar:自定义比较函数指针(核心!考试编程题必考)—— 需手动编写,规则如下:
函数参数:两个const void
(通用指针,需强制转换为对应数据类型);
返回值:int 型,决定排序规则:
✅ 若a > b,返回正数;
✅ 若a < b,返回负数;
✅ 若a == b,返回0;
示例逻辑:排序 int 数组升序,返回(int)a - (int)b;降序则返回(int)b - (int)a。

三、核心使用规则(考试编程题考点)

必须自定义比较函数:qsort本身不判断元素大小,完全依赖比较函数的返回值;
void指针不可直接解引用:比较函数中需先将const void强制转换为对应类型(如int、char),再解引用比较;
通用性:同一套qsort逻辑可排序不同类型数组,仅需修改比较函数。

四、考试高频易错点

头文件遗漏:未包含<stdlib.h>,导致qsort未定义(编译报错,判断题必考);
比较函数错误:
参数未用const void(类型不匹配);
未强制转换指针类型直接解引用(如
a,报错);
返回值逻辑搞反(升序 / 降序颠倒);
格式错误:size_t类型的nitems/size用%d输出(正确是%zu);
参数传错:size传成数组总大小(应传单个元素大小)、nitems传成数组字节数(应传元素个数)。

总结

qsort需包含<stdlib.h>,核心是自定义比较函数,支持任意类型数组排序;
比较函数必须将void*强制转换为对应类型,返回值决定排序升 / 降序;
易错核心:指针类型转换、size_t格式%zu、参数传值(单个元素大小 / 元素个数)。

一、<stdio.h>(输入输出库,最高频)

所有函数需包含#include <stdio.h>,核心考点:
输入类:scanf()(格式化输入)、getchar()(单个字符输入)、fgets()(带空格字符串输入,替代废弃的gets());
易错:scanf("%c")需处理缓冲区\n;fgets()会读取\n并存入字符串。
输出类:printf()(格式化输出)、putchar()(单个字符输出)、puts()(字符串输出,自动换行);
易错:printf格式符与参数类型匹配(如time_t用%ld);puts仅输出字符串,不能输字符 / 数字。

二、<stdlib.h>(通用工具库,高频)

所有函数需包含#include <stdlib.h>,核心考点:

  1. qsort():通用快速排序(支持任意类型数组);
    易错:自定义比较函数需强制转换void*指针;size_t类型输出用%zu。
  2. malloc()/free():动态内存分配;
    malloc(size):分配size字节内存,返回void*(需强制转换类型),失败返回NULL;
    free(p):释放动态内存,用完必须释放(避免内存泄漏);
    易错:未判空malloc返回值;重复释放 / 释放非动态内存。
  3. atoi()/atof():字符串转数值;
    atoi(str):字符串转int,非数字字符串返回 0;atof(str):字符串转double。
  4. abs():整数绝对值(浮点型绝对值用<math.h>的fabs())。

三、<string.h>(字符串处理库,最高频)

所有函数需包含#include <string.h>,核心考点:
strlen():求字符串有效长度(不含'\0');
易错:与sizeof区分(sizeof算数组总字节,strlen算有效字符数);输出用%zu。
strcpy()/strncpy():字符串拷贝;
strcpy(dst, src):拷贝含'\0',无长度校验(易溢出);strncpy(dst, src, n):最多拷贝n个字符,更安全;
易错:dst数组需足够大;禁止拷贝自身(dst=src)。
strcat()/strncat():字符串拼接;
易错:dst需有足够空间;拼接前dst必须以'\0'结尾。
strcmp():字符串比较(按 ASCII 码);
返回值:str1>str2返回正数,相等返回 0,小于返回负数;
易错:误判返回值(如用res1判断相等,正确是res0)。

四、<math.h>(数学函数,中频)

所有函数需包含#include <math.h>,核心考点:
sqrt():平方根(如sqrt(4)返回2.0,double型);
pow():幂运算(如pow(2,3)返回8.0,参数 / 返回值均为double);
fabs():浮点型绝对值(整数用abs());
易错:参数 / 返回值为double,输出用%f;漏加头文件导致编译报错。

五、<ctype.h>(字符判断 / 转换,中频)

所有函数需包含#include <ctype.h>,核心考点:

  1. isdigit():判断字符是否为数字('0'-'9'),是返回非 0,否返回 0;
  2. isalpha():判断字符是否为字母(a-z/A-Z);
  3. tolower()/toupper():字符转小写 / 大写(如tolower('A')返回'a');
    易错:参数传字符(如'5'),而非数字(5);返回值是int,需强转char。

六、<time.h>(时间函数,中频)

所有函数需包含#include <time.h>,核心考点:
易错:tm_year需 + 1900、tm_mon需 + 1;通过指针访问成员用->。
ctime()/asctime():转换为可读字符串(自带\n)

  1. time () 函数(最高频)
    功能:获取当前系统的时间戳(从 1970-01-01 00:00:00 到当前时刻的秒数);
    用法:time_t t = time(NULL);(参数传 NULL 即可,返回值存入 time_t 变量);
    易错:time_t是长整型,输出需用%ld格式(而非%d),否则输出乱码 / 错误值。
  2. localtime () 函数(最高频)
    功能:将time_t类型的时间戳转换为本地时间的struct tm结构体(拆分出年月日时分秒);
    struct tm核心成员(考试必考,易错偏移):
    tm_year:年份,存储值 = 实际年份 - 1900(如 2026 年存为 126,需 + 1900 才是真实年份);
    tm_mon:月份,0-11(0=1 月,11=12 月,需 + 1 才是真实月份);
    tm_mday:日期(1-31,无偏移);
    tm_hour:小时(0-23)、tm_min:分钟(0-59)、tm_sec:秒(0-59);
    用法:struct tm *local_t = localtime(&t);(参数是 time_t 变量的地址,返回结构体指针);
    易错:忘记给tm_year+1900、tm_mon+1,导致年份 / 月份输出错误;通过指针访问成员需用->(如local_t->tm_year),而非.。
  3. ctime () 函数(中频)
    功能:直接将时间戳转换为人类可读的字符串(格式如:Sun Jan 11 10:30:00 2026\n);
    用法:char *time_str = ctime(&t); printf("%s", time_str);;
    易错:返回的字符串末尾自带\n,输出时无需手动加换行;字符串是静态数组,多次调用会覆盖之前的内容。
  4. asctime () 函数(中频)
    功能:将struct tm结构体转换为可读字符串(格式同 ctime);
    用法:char *str = asctime(local_t);(参数是 tm 结构体指针)。。

posted on 2026-01-11 17:03  lQvQe  阅读(7)  评论(0)    收藏  举报