学C语言最怕什么?最怕学完了一学期,能看懂每行代码在干啥,但让自己从头写个东西就抓瞎。或者考试能过,但面试一问“指针和数组有什么区别”就支支吾吾。
说白了,会做题不代表真懂,真懂的标准是:给你一个需求,你能用C语言把它干净利落地实现出来,并且知道自己每一行代码在内存里干了什么。
下面我把C语言必须掌握的知识点从头到尾捋一遍。你对照着看,哪个地方还含糊,那就是你的薄弱环节。手边没有电脑,拿起手机,打开在线编程环境https://sky315.com:8080/c/赶紧练。
一、地基部分——变量、数据类型、运算符、表达式
这部分看着简单,但很多人学完了一知半解。
数据类型你得搞清楚:int、char、float、double各占多少字节(不同平台可能不一样,但你要知道怎么查),什么场景用哪个。整型还分short、long、unsigned,别混着用。字符型本质上是整数,'A'就是65,这个弯转不过来后面字符串就学不明白。
常量与变量:常量的几种写法——整型常量、浮点常量、字符常量、字符串常量,还有用#define和const定义的符号常量,区别在哪你得知道。变量就是给内存地址起了个好记的名字,这个理解要刻在脑子里。
运算符:算术运算符(+ - * / %)没什么好说的,但%只能用于整数,很多人踩过坑。自增自减(++、--)是C语言的特色,前置和后置的区别必须搞明白,i++和++i在表达式里的行为不一样。关系运算符(> < == !=)和逻辑运算符(&& || !)是写条件判断的基础,优先级要记牢。赋值运算符、复合赋值运算符(+=、-=这些)要熟练。逗号运算符、条件运算符(? :)算是锦上添花,但最好也掌握。
类型转换:整型和浮点型混在一起运算时会发生什么?自动类型转换的规则是什么?强制类型转换怎么写、什么时候用?这些搞不清楚,算出来的结果经常莫名其妙。
输入输出:printf和scanf是C语言最常用的两个函数,格式控制符(%d、%f、%c、%s这些)必须倒背如流。getchar、putchar也顺带掌握。
二、程序的骨架——三种控制结构
C语言是结构化程序设计语言,任何程序都能用三种结构写出来:顺序、选择、循环。
顺序结构最简单,就是从main函数开始一行一行往下执行。但你要知道C程序是由函数构成的,有且只有一个main函数,程序从它开始,到它结束。
选择结构:if语句的三种形式(if、if-else、if-else if-else)。else和最近的if配对,这个规则不知道的话,缩进写得再好看也没用。switch语句配合case、break、default,注意case后面没有break就会一直往下执行,这叫“穿透”,有时候是特性有时候是Bug。
循环结构:while、do-while、for三种。区别是什么?do-while至少执行一次。for的三个表达式各是干什么的、执行顺序是什么。循环嵌套怎么控制。break跳出当前循环,continue跳过本次循环后面的语句直接进入下一次。别搞混了。
三、批量处理数据——数组
数组就是把同一类型的一堆变量排好队,用下标来访问。
一维数组:定义、初始化、访问。数组名是什么?数组名是地址,是首元素的地址。这个理解不到位,后面指针和数组的关系就捋不清。
二维数组:本质上是一维数组的数组。行优先存储,内存里是连续的一块。
字符数组和字符串:C语言没有专门的字符串类型,字符串就是以'\0'结尾的字符数组。这就意味着字符数组的长度要比实际字符串多一位存结束符。字符串处理函数(strlen、strcpy、strcat、strcmp等)要会用,更要理解它们是怎么工作的——靠的就是找那个'\0'。
四、代码复用的武器——函数
函数是C语言最基本的结构化单位。不会用函数,写出来的代码就是一大坨。
函数的定义和调用:返回值类型、函数名、参数列表、函数体。
参数传递:C语言是值传递。你把变量传给函数,函数拿到的是它的副本,在函数里改了不影响外面的变量。那怎么让函数修改外面的变量?用指针传地址。这个逻辑链条要通。
作用域和存储类别:局部变量和全局变量。auto、static、register、extern这几个关键字是干什么的。static修饰局部变量会让它生命周期变长,static修饰全局变量会限制它只在当前文件可见。这些细节面试常考。
函数的嵌套调用和递归:递归是函数调用自己,写递归要有终止条件。
五、C语言的灵魂——指针
指针是C语言最核心也最难啃的部分。很多人学到这里就放弃了,但指针才是C区别于其他语言的精髓。
指针的基本概念:指针就是地址,指针变量就是存放地址的变量。你要理解内存的编址方式,理解变量在内存里怎么存的。
指针的运算:指针加减整数是什么意思?不是简单的地址加减,而是以指向的类型大小为单位移动。
指针和数组:数组名是地址,可以用指针遍历数组。数组名和指针不是一回事——数组名是常量地址,不能赋值;指针是变量,可以指向不同地方。这个区别要搞清楚。
指针和函数:指针作为函数参数可以实现“传址”。函数指针——指向函数的指针,可以把函数当参数传来传去。
多级指针:指向指针的指针。二维数组和二级指针的关系要理顺。
动态内存分配:malloc、calloc、realloc、free。堆和栈的区别。申请了内存用完要释放,不然内存泄漏。释放之后指针要置NULL,不然变成野指针。野指针和空指针的区别要知道。
六、自定义数据类型——结构体、共用体、枚举
结构体struct:把不同类型的数据打包成一个整体。结构体变量的定义、访问成员(用.运算符)、结构体指针(用->运算符)。结构体在内存里怎么排列的(内存对齐)——这个偏底层但理解了会让你对内存有更深的认识。
共用体union:所有成员共享同一块内存,大小等于最大的成员。同一时间只能用一个成员。用得少,但要知道它和结构体的区别。
枚举enum:给整数起个有意义的名字,提高代码可读性。
typedef:给类型起别名。让代码更简洁、更可移植。
七、文件的读写——让数据持久化
程序跑完数据不能丢,得存到文件里。
文件指针FILE*:打开文件用fopen,关闭用fclose。
读写函数:fgetc/fputc(字符级)、fgets/fputs(字符串级)、fread/fwrite(二进制块级)、fprintf/fscanf(格式化读写)。
文件定位:fseek、ftell、rewind。
文本文件和二进制文件的区别要知道。
八、进阶但不应该忽略的东西
预处理指令:#include、#define(宏定义)、#ifdef/#ifndef/#endif(条件编译)。宏和函数的区别——宏只是文本替换,没有类型检查。
位运算:&、|、^、~、<<、>>。虽然平时用得不多,但在底层开发、嵌入式、网络协议解析里是基本功。
链表:用结构体和指针实现动态数据结构。单向链表的基本操作(创建、插入、删除、遍历)要能手写。
最后说两句:
上面列了这么多,看着吓人,但你仔细捋一捋就会发现,C语言的知识点其实是有逻辑链条的:变量怎么存→怎么控制流程→怎么批量处理→怎么复用代码→怎么操控内存→怎么组织复杂数据→怎么持久化。每一步都是下一步的基础。
融会贯通的标准是什么? 不是背得出所有知识点,而是给你一个需求,你能自然地想出来:用什么数据类型、用什么控制结构、要不要定义函数、要不要用指针、用不用结构体——脑子里有一幅清晰的图。另外说一句,光看不练等于零。C语言是练出来的,不是看出来的。每个知识点学完,自己动手敲代码,跑起来,改出Bug再修好,这个过程才是真把知识变成自己的。
对照上面这份清单,哪个地方还心虚,就回去重点补。补完了,C语言这关你就真正过去了。