当前位置: 首页 > news >正文

C语言核心知识体系总结

C语言核心知识体系总结

本文旨在系统梳理C语言的基础与进阶知识点,帮助读者建立清晰的知识框架。内容涵盖:程序编译过程、数据类型与变量、运算符与表达式、控制结构、函数、指针、结构体与共用体、动态内存分配、文件操作等。适合复习巩固或查漏补缺。


第一章 程序编译与基础概念

1.1 程序设计四步骤

  1. 编辑:创建以.c为扩展名的源程序文件。
  2. 编译:将源代码编译成目标文件(.obj.o)。
  3. 链接:将目标文件与库文件链接成可执行文件(.exe)。
  4. 运行:执行可执行文件。

1.2 格式化输出与转换说明符

  • 双引号内的内容称为格式化字符串,会原样输出(除转义字符和格式占位符外)。
  • 常用转换说明符:
说明符含义
%d有符号十进制整数(32位)
%lld有符号64位整数
%u无符号32位整数
%c字符
%f浮点数(小数形式)
%p地址
%x/%llx十六进制整数(32/64位)
%s字符串
  • &是取地址符,告诉变量在内存中的位置。
  • 注意scanf不会主动吃掉输入缓冲区中的回车或空格;但读取数值时,会自动跳过空白字符(空格、回车、制表符)。

1.3 注释方式

  • 段落注释/* 注释内容 */
  • 行注释// 注释内容(C99及以后)

1.4 标识符命名规则

  • 只能由字母、数字、下划线及$组成,不能以数字开头
  • 不能使用关键字或保留字。
  • 推荐驼峰命名法,见名知意。
    • 类名/接口名:首字母大写,后面每个单词首字母大写。
    • 变量名/方法名:首字母小写,后面每个单词首字母大写。
    • 常量名:全部大写,单词间用下划线_分隔。
    • 包名:全部小写,单词间用下划线(或点)分隔。

1.5 程序三种基本结构

  • 顺序结构
  • 选择结构
  • 循环结构

共同特点:单入口单出口,每一部分都可能被执行,且不存在“死循环”。

1.6 机器数与原反补码

  • 机器数:符号位(0正1负)+ 数值位,是计算机中二进制表示形式。
  • 三种形式:原码、反码、补码。负数以补码形式存储。
    • 正数:原码 = 反码 = 补码。
    • 负数:反码 = 原码符号位不变,数值位取反;补码 = 反码 + 1。
  • ~是按位取反(包括符号位)。

1.7 运算符优先级与转义字符

  • 优先级:算术运算符 > 关系运算符 > 赋值运算符
  • 常用转义字符:
符号含义
\0字符串结束标志(不计入长度)
\n换行
\r回车
\t水平制表符
\\反斜杠
\"双引号
\'单引号
\a响铃
\b退格
\xhh十六进制 ASCII 字符
\ooo八进制 ASCII 字符

1.8 头文件引用方式

  • 尖括号<>:编译器直接到标准头文件目录查找。
  • 双引号"":先在当前源文件所在目录查找,再到标准目录查找。

1.9 命令行、终端、Shell、流文件

  • 控制台:物理设备(屏幕+键盘+鼠标),人机交互。
  • 终端:文本输入输出环境(一个窗口)。
  • Shell:命令行解释器,处理用户命令。
  • 流文件:对数据具有过滤、编码、压缩、加密等处理能力的文件抽象。

第二章 常量、变量与数据类型

2.1 数据、变量、常量的关系

以整型为例:整型变量用于存储整型常量。其他类型同理。

2.2 变量分类

  • 按作用域:全局变量、局部变量。
  • 按存储方式
    • 静态存储:编译时分配固定空间(全局变量、静态局部变量)。
    • 动态存储:运行时分配,使用完释放(形参、局部变量、函数调用现场等)。

2.3 变量的作用域与生命周期

  • 静态变量:从程序开始到结束。
  • 动态变量:从所在函数开始执行到函数结束。

2.4 局部变量的存储类别

类别关键字特点
自动auto动态存储,未初始化时值为随机,可省略
静态static静态存储,未初始化默认为0,作用域限于本文件
寄存器register建议存储于CPU寄存器(现代编译器自动优化,已少用)
外部extern声明外部变量/函数,使其他文件的全局变量可用

2.5 常量类型

  • 整型常量、实型常量(小数、指数)、字符常量(普通/转义)、符号常量(#define)、枚举常量enum)。
  • 枚举常量:自定义一组整数常量,编译器将其视为整数。

2.6 数据类型概览

  • 基本类型:整型、浮点型。
  • 枚举类型
  • 派生类型:指针、数组、结构体、共用体、函数。
  • 空类型void

C语言没有原生字符串类型,字符串以字符数组存储。

2.7 类型转换

  • 混合运算时:

    • 若一个操作数为floatdouble,结果提升为double
    • intfloat/double运算,先转为double
  • 赋值时的转换:

    • 浮点 → 整型:取整。
    • 整型 → 浮点:自动转为浮点数。
    • 字符 → 整型:存入ASCII码。
  • 数组定义:int arr[10];数组大小必须用常量表达式。


第三章 常用库函数、关键字与控制结构

3.1 常用函数

函数头文件功能
sleep(秒)windows.h程序暂停指定时间
system("命令")stdlib.h执行系统命令(如cls清屏)
fabs(x)/abs(x)math.h取浮点数/整数绝对值
pow(x, y)math.h计算 x 的 y 次方
scanfstdio.h格式化输入(空格/Tab/回车分隔)

3.2 关键字(32个)

类别关键字
数据类型int,char,float,double,void,enum,struct,union
存储类auto,static,register,extern
修饰符const,signed,unsigned,volatile
控制语句if,else,switch,case,default,for,while,do,break,continue,goto,return
其他sizeof,typedef

重要说明

  • sizeof返回unsigned int类型,与有符号int比较时需注意类型提升。
  • static修饰局部变量:生命周期延长至整个程序;修饰全局变量/函数:作用域限于本文件(内部链接)。
  • extern:声明外部变量或函数,可在其他源文件中使用。
  • typedef:为已有类型创建别名。
  • #define预处理指令,不是关键字。

3.3 选择结构

  • if语句:单分支、双分支、多级嵌套。
  • switch语句:表达式必须为整型,case后跟整型常量表达式。

3.4 循环结构

  • while:当型循环,先判断后执行。
  • do...while:直到型循环,至少执行一次。
  • forfor(表达式1; 表达式2; 表达式3),三个表达式均可省略(但分号不能省)。continuefor中会执行表达式3。

3.5 三目运算符

表达式 ? 表达式1 : 表达式2— 表达式非零则执行1,否则执行2。

附:函数、关键字、操作符的区别

  • 关键字和操作符:语言内置,不可自定义。
  • 函数:可自定义名字,有独立代码段,调用时入栈跳转;操作符在本地直接运算。

第四章 字符串处理函数

使用以下函数需要包含头文件#include <string.h>

函数原型功能
puts(str)输出字符串(自动换行)
gets(str)输入字符串(可包含空格,以回车结束)不安全,推荐fgets
strcat(s1, s2)将 s2 连接到 s1 后面(s1 必须足够大)
strcpy(s1, s2)/strncpy(s1, s2, n)字符串复制(逐个字符,包括\0
strcmp(s1, s2)比较字符串,返回:0 相等;>0 表示 s1>s2;<0 表示 s1<s2
strlen(s)返回字符串长度(不含\0
strlwr(s)/strupr(s)转换为小写/大写(非标准,部分编译器支持)
strtok(s, delim)分割字符串(会修改原串)

第五章 函数

5.1 C程序组成

  • 一个程序由一个或多个源程序文件组成(编译单位)。
  • 一个源文件由一个或多个函数组成。
  • main函数是程序入口和出口。
  • 所有函数平行,可相互调用,但main不能被其他函数调用。

5.2 函数分类

  • 库函数 vs 自定义函数。
  • 有参函数 vs 无参函数。

5.3 函数使用要点

  • 若函数定义在调用之后,需函数声明
  • 可将声明写在文件开头(全局声明),则整个文件都可调用。
  • 函数可以嵌套调用,如max(a, max(b, c))

5.4 参数传递

  • 传值:实参的值拷贝给形参,形参改变不影响实参。
  • 传地址(指针):实参地址传给形参,形参操作会影响实参。
  • 数组元素作为实参 → 传值。
  • 数组名作为实参 → 传地址(数组首元素地址),形参改变会影响实参。
  • 二维数组作形参时,行数可省略,列数不能省略

5.5 全局变量与局部变量同名

  • 在函数内,局部变量会屏蔽全局变量(同名时自动使用局部变量)。

5.6 内部函数与外部函数

  • 内部函数static 类型 函数名(...),仅本文件可调用。
  • 外部函数:默认或加上extern,可被其他文件调用。

第六章 指针(上)

6.1 指针基础

  • 内存按字节编号,每个编号称为内存地址
  • 指针:存储变量地址的变量。
  • 定义:int *p;// p 是指向 int 的指针
  • 解引用:*p = 10;// 给 p 指向的内存赋值
  • 空指针:NULL(在stdio.h中定义为 0)。

6.2 指针的类型

  • 指针变量本身的类型(基类型)——如int *char *
  • 指针所指向数据的类型。

为什么基类型必须与指向变量类型相同?
因为不同类型占用字节数不同,若char*指向int变量,解引用时只会访问第一个字节,无法正确读取整个整数。

6.3 数组与指针

  • 数组名是指针常量(首元素的地址)。
  • 通过指针访问数组:int *p = arr;*(p+i)等价于arr[i]
  • 相邻数组元素的地址相差1 个元素类型的大小(字节数)。

6.4 指针运算

  • 指针加 1:地址增加sizeof(类型)字节。
  • 指针减指针:结果为两个指针之间的元素个数(要求指向同一数组)。
  • 指针可比较大小(同类型,同数组)。

6.5 指向字符数组的指针

char*p="hello";// p 指向字符串常量(只读)charstr[]="hello";char*q=str;// 指向字符数组(可修改)

6.6 函数指针与指针函数

  • 函数指针:指向函数的指针,int (*p)(int, int);
  • 指针函数:返回值为指针的函数,int *func(int a, int b);

第七章 指针(下)与动态内存分配

7.1 动态内存分配函数(stdlib.h

函数功能
malloc(size)分配size字节的连续内存,返回首地址(void*
calloc(n, size)分配nsize字节的内存,并初始化为 0
realloc(ptr, new_size)重新调整已分配内存的大小
free(ptr)释放动态分配的内存

7.2 内存泄漏

动态分配的内存若未用free释放,且指针丢失,会导致内存泄漏(程序结束前无法再使用该内存)。虽程序结束后操作系统会回收,但长期运行的程序(如服务器)必须及时释放。

7.3 常见错误

  • 使用未初始化的指针(野指针)。
  • 重复释放内存(double free)。
  • 释放后继续使用(悬空指针)。

第八章 用户自定义类型

8.1 结构体(struct)

定义
structStudent{charname[20];intage;floatscore;};
使用
  • 定义变量:struct Student stu1;
  • 初始化:struct Student stu1 = {"张三", 20, 90.5};
  • 访问成员:stu1.agep->age(指针访问)。
  • 结构体变量可整体赋值(同类型)。
  • 结构体作函数参数:可传值、传指针(推荐传指针,效率高)。
结构体指针
structStudent*p=&stu1;p->age=21;// 等价于 (*p).age = 21;

8.2 链表

  • 链表是一种动态数据结构,由结点组成,每个结点包含数据域和指针域。
  • 结点通常用结构体定义:
structNode{intdata;structNode*next;};
  • 动态创建结点:malloc,并手动链接。

8.3 共用体(union)

  • 所有成员共用同一段内存(大小等于最大成员)。
  • 同一时刻只能存储一个成员的值。
  • 访问方式:union Data d; d.i = 10;
  • 常用于节省内存或数据类型转换。

8.4 枚举类型(enum)

enumColor{RED,GREEN,BLUE};enumColorc=RED;
  • 枚举元素默认从 0 开始,可手动赋值。
  • 枚举变量通常当作整数使用。

8.5 typedef 的用法

typedefintInteger;// 为 int 起别名typedefstructStudentStudent;// 为结构体起别名typedefintArray[10];// 为数组类型起别名typedefint*Ptr;// 为指针类型起别名typedefint(*FuncPtr)(int,int);// 为函数指针起别名

作用:简化代码,增强可读性,便于跨平台编程。


第九章 文件操作

9.1 文件分类

  • 程序文件:源文件(.c)、目标文件(.obj)、可执行文件(.exe)。
  • 数据文件:程序运行时读写的数据文件。

9.2 存储方式

  • ASCII 文件(文本文件):每个字节存储一个字符,可读性好,占用空间大。
  • 二进制文件:按内存存储格式直接存放,占用空间小,不可直接阅读。

9.3 文件缓冲区

系统为每个打开的文件在内存中开辟一个缓冲区。输入/输出数据先经过缓冲区,再实际读写。

9.4 文件指针(FILE*)

FILE*fp;fp=fopen("test.txt","r");if(fp==NULL){// 打开失败}

打开方式

模式含义
"r"只读(文件必须存在)
"w"只写(文件不存在则创建,存在则清空)
"a"追加(在文件末尾写入)
"rb"/"wb"/"ab"二进制读写

9.5 常用文件读写函数

函数功能
fgetc(fp)读一个字符,返回 EOF(-1) 表示失败或文件尾
fputc(ch, fp)写一个字符,返回 EOF 表示失败
fgets(buf, n, fp)读一行(最多 n-1 个字符)
fputs(str, fp)写字符串
fprintf(fp, format, ...)格式化写入
fscanf(fp, format, ...)格式化读取
fread(ptr, size, count, fp)二进制读取
fwrite(ptr, size, count, fp)二进制写入
feof(fp)判断是否到达文件末尾(光标后无字符)

9.6 关闭文件

fclose(fp);

不关闭文件会导致缓冲区数据未写入外存,造成数据丢失。

9.7 标准流

程序启动时自动打开三个标准流:

  • stdin(标准输入)—— 通常键盘
  • stdout(标准输出)—— 通常屏幕
  • stderr(标准错误)—— 通常屏幕

终端就是与这些流交互的外围设备。


附录:常见疑问速查

问题答案
为什么指针要有基类型?因为解引用时需要知道访问多少字节,以及如何解释数据。
strlensizeof的区别?strlen计算字符串长度(不含\0),sizeof计算变量或类型占用的字节数。
动态内存分配后忘记free会怎样?造成内存泄漏,程序长时间运行可能耗尽内存。
数组名为什么不能自增?数组名是常量指针,不能作为左值被修改。
typedef#define的区别?typedef在编译阶段处理,产生类型别名;#define预处理阶段简单文本替换。
局部变量未初始化为什么是随机值?局部变量分配在栈上,保留了上次函数调用留下的旧数据。静态变量默认初始化为 0。

本文总结自C语言学习笔记,如有疏漏欢迎补充。掌握这些基础,是深入学习数据结构、操作系统、嵌入式开发等的基石。

http://www.jsqmd.com/news/799964/

相关文章:

  • ESP32开发板选型指南:为什么NodeMCU-32S是新手入门的最佳选择?
  • GDB太慢?试试用addr2line给你的C/C++程序做“尸检报告”
  • 2026酒店中央净水系统厂家推荐:直饮水设备生产厂家,一站式解决方案 - 栗子测评
  • AI Skills自动图文助手|全场景技能包一键调用
  • 最高月薪50k!AI再厉害,也离不开人工实测,车载测试人才依然吃香
  • Driver Store Explorer深度解析:Windows驱动存储管理的终极解决方案
  • 告别GPS依赖:用PTP协议和本地高精度晶振,搭建一个更可靠的工业级时间同步系统
  • 上海亚卡黎实业2026优选车载式高空作业平台厂家:高空作业车品牌/生产厂家/厂家推荐上海亚卡黎实业有限公司 - 栗子测评
  • 流化床式气流粉碎机厂家推荐:2026粉体搅拌混合机/超微粉碎机粉体设备生产厂家实力解析 - 栗子测评
  • 基于GitHub数据构建AI人才知识图谱:技术架构与工程实践
  • 二叉树与递归:解锁高级数据结构的编程内功心法
  • FastAPI + SQLAlchemy 异步 ORM实现自动建表
  • 保姆级教程:用Python和NumPy手把手复现MIMO信道SVD分解与预编码(附代码)
  • RK3399 eMMC硬件设计中的启动模式与信号完整性考量
  • 基于OpenClaw框架的智能园艺助手:AI Agent与文件即记忆的实践
  • 基于Twilio与ChatGPT构建AI电话助手:架构设计与实战指南
  • Blueberry印相失效全归因分析,深度解读--stylize权重错配、种子漂移及提示词氧化导致的蓝调衰减现象
  • 基于RAG的本地知识库聊天机器人:anything-llm部署与实战指南
  • 如果真有外星人,快把我带走吧,换个坑
  • 【Android Q】super分区metadata结构深度剖析与实战解析
  • 基于CrewAI的多智能体自主开发团队:从原理到工程实践
  • 【实战】T100开发核心:从Genero FGL到帆软报表的进阶指南
  • 基于 HM-TM32 红外摄像头:棉花燃烧+起火自动录制 30 秒视频
  • 自定义标签切换动画
  • 新公司也能报高企?申报全攻略
  • 从‘对表’到‘心跳’:用Wireshark抓包带你读懂IEEE1588(PTP)协议报文交互全过程
  • 树莓派无显示器?三种方法搞定WiFi配置,新手也能5分钟连上网
  • AI撕掉了我们的“岗位说明书”,然后呢?
  • 别再想当然!用AD628做单电源信号调理,你必须先算清楚这两个公式(附计算工具)
  • BAETYL v2 边缘计算框架:云原生架构、核心组件与生产部署实战