C 语言是一门面向过程的高级编程语言,诞生于 20 世纪 70 年代,兼具高级语言的简洁易懂与底层语言的硬件操控能力,是学习编程的经典入门语言。
C 语言语法精简,没有过多封装,能够直接操作内存地址,运行效率极高,广泛用于操作系统、驱动程序、嵌入式设备、底层工具开发。Linux 内核、单片机程序大多基于 C 语言编写。
C 语言不提供自动内存管理,需要开发者手动管理内存,对编程思维要求更高。虽然诞生较早,但至今仍是计算机专业的基础必修课,学好 C 语言,能够帮助理解计算机底层运行逻辑,为后续学习其他语言打下扎实基础。
一、C语言核心特点(为什么必须学C?)
-
底层性强:可直接操作内存、硬件,贴近计算机底层,是操作系统、单片机、嵌入式开发核心语言。
-
结构化清晰:顺序、分支、循环三大结构,逻辑严谨,适合培养编程思维。
-
执行效率高:编译后生成机器码,无冗余开销,运行速度远超Python、Java等解释型语言。
-
通用性极强:跨平台兼容,Windows、Linux、Mac、嵌入式设备均可运行。
-
基石属性:C++、Java、Python等绝大多数语言语法均借鉴C语言,学会C一通百通。
二、C语言运行原理(流程图详解)
2.1 完整开发运行流程
C语言是编译型语言,必须经过「编写代码→编译→链接→运行」四大步骤,和Python即时运行完全不同,完整流程可视化如下:
2.2 核心文件说明
-
.c源文件:手写的代码文件,纯文本格式,无法直接运行
-
.obj目标文件:编译后的二进制中间文件,未整合系统库
-
.exe可执行文件:最终成品,双击即可运行,计算机可直接识别
三、第一个C语言程序(Hello World )
3.1 完整可运行代码
- #include <stdio.h> // 头文件引入
- int main() // 主函数,程序唯一入口
- {
- // 输出语句,打印内容到控制台
- printf("Hello C语言!零基础入门\n");
- return 0; // 程序正常结束,返回0
- }
复制代码3.2 逐行精准解析(新手必看)
-
#include :预处理指令,引入标准输入输出头文件。printf、scanf等输入输出函数都定义在这个文件中,没有这行代码,程序无法识别打印语句。
-
int main():主函数,所有C语言程序的唯一入口,程序运行时会自动从main函数开始执行,一个项目有且仅有一个main函数。int代表函数返回值为整数类型。
-
{}:代码块包裹符,大括号内部是函数的具体执行逻辑,成对出现,缺一不可。
-
printf():标准输出函数,功能是向控制台打印字符串、数字等内容,\n是换行符。
-
return 0;:表示程序正常终止,返回0给操作系统,非0代表程序异常结束。
-
// 注释:单行注释,仅用于程序员备注,编译器会直接忽略,不参与程序运行。
四、C语言核心语法体系(基础核心)
4.1 变量与数据类型(存储数据的容器)
编程的核心是处理数据,变量就是存放数据的容器,C语言必须先定义、后使用变量。
4.1.1 四大基础数据类型
| 数据类型 | 占用空间 | 存储内容 | 示例 |
|---|
| int(整型) | 4字节 | 整数(正负整数、0) | int a = 10; |
| float(单精度浮点) | 4字节 | 小数(精度6-7位) | float b = 3.14f; |
| double(双精度浮点) | 8字节 | 高精度小数(15-16位) | double c = 3.1415926; |
| char(字符型) | 1字节 | 单个字符(字母、符号) | char d = ‘A’; |
4.1.2 变量定义规则
4.2 输入输出函数(人机交互)
4.2.1 printf 输出函数
用于打印数据,搭配格式占位符输出不同类型数据:
-
%d:输出整型 int
-
%f:输出浮点型 float/double
-
%c:输出字符型 char
-
%s:输出字符串
- #include <stdio.h>
- int main()
- {
- int age = 20;
- float score = 95.5;
- char ch = 'C';
- printf("年龄:%d\n", age);
- printf("分数:%f\n", score);
- printf("字符:%c\n", ch);
- return 0;
- }
复制代码4.2.2 scanf 输入函数
用于接收用户键盘输入,必须加取地址符&(字符串除外)
- #include <stdio.h>
- int main()
- {
- int num;
- printf("请输入一个整数:");
- scanf("%d", &num); // &获取变量内存地址
- printf("你输入的数字是:%d", num);
- return 0;
- }
复制代码4.3 运算符(数据运算)
4.3.1 算术运算符
+、-、*、/、%(取余),重点注意:整数相除结果为整数(5/2=2),取余仅支持整数
4.3.2 关系运算符
>、<、>=、<=、==(等于)、!=(不等于),运算结果只有真(1)、假(0)
4.3.3 逻辑运算符
&&(与,全真才真)、||(或,一真即真)、!(非,真假反转)
五、C语言三大流程结构(核心逻辑,流程图全覆盖)
所有C语言程序逻辑,均由顺序、分支、循环三种结构组成,无第四种结构。
5.1 顺序结构
默认执行逻辑:从上到下、逐行依次执行,无跳转、无判断,是最基础的结构,所有复杂程序都基于顺序结构延伸。
5.2 分支结构(判断选择)
根据条件是否成立,选择不同代码执行,包含if、if-else、if-else if、switch四种用法。
5.2.1 if-else 双分支结构
- #include <stdio.h>
- int main()
- {
- int score;
- scanf("%d", &score);
- if(score >= 60){
- printf("及格");
- }else{
- printf("不及格");
- }
- return 0;
- }
复制代码5.2.2 switch 多分支结构
适合固定值判断(如星期、等级),避免多层if嵌套,搭配break跳出分支
适合固定值判断(如星期、等级),避免多层if嵌套,搭配break跳出分支
- #include <stdio.h>
- int main()
- {
- int week;
- scanf("%d", &week);
- switch(week){
- case 1: printf("星期一"); break;
- case 2: printf("星期二"); break;
- default: printf("输入错误"); break;
- }
- return 0;
- }
复制代码5.3 循环结构(重复执行代码)
满足条件时,重复执行某段代码,大幅减少重复代码,包含while、do-while、for三种循环。
5.3.1 while 循环(先判断、后执行)
- #include <stdio.h>
- int main()
- {
- int i = 1;
- while(i <= 5){ // 循环条件:i小于等于5
- printf("循环执行:%d\n", i);
- i++; // 变量自增,避免死循环
- }
- return 0;
- }
复制代码5.3.2 for 循环(最常用,结构最简洁)
整合初始化、条件判断、变量更新,是工程中使用最多的循环结构,适合已知循环次数的场景。
- 在#include <stdio.h>
- int main()
- {
- // 1.初始化i=1;2.判断i<=5;3.每次循环结束i++
- for(int i = 1; i <= 5; i++){
- printf("for循环执行:%d\n", i);
- }
- return 0;
- }
复制代码5.3.3 do-while 循环(先执行、后判断)
唯一先执行、后判断的循环,无论条件是否成立,代码至少执行一次,适合菜单、交互类场景。
- #include <stdio.h>
- int main()
- {
- int i = 1;
- do{
- printf("do‑while循环执行:%d\n", i);
- i++;
- }while(i <= 5); // 条件写在末尾分号不能丢!
- return 0;
- }
复制代码5.3.4 循环关键字:break & continue
- //break
- #include <stdio.h>
- int main()
- {
- for(int i = 1; i <= 5; i++){
- if(i == 3){
- break; // i等于3直接跳出整个for循环
- }
- printf("break演示 i=%d\n", i);
- }
- printf("循环已经结束\n");
- return 0;
- }
复制代码- //continue
- #include <stdio.h>
- int main()
- {
- for(int i = 1; i <=5; i++){
- if(i == 3){
- continue; // i=3时跳过后面printf,直接i++进入下一轮
- }
- printf("continue演示 i=%d\n", i);
- }
- return 0;
- }
复制代码六、数组(批量存储同类数据)
单个变量只能存一个数据,数组可以存储一组相同类型的数据,分为一维数组、二维数组。
6.1 一维数组
定义格式:数据类型 数组名[长度] = {初始值};
- #include <stdio.h>
- int main()
- {
- // 存储5个学生成绩
- int score[5] = {80,90,75,88,92};
- // 遍历数组
- for(int i = 0; i < 5; i++){
- printf("第%d个成绩:%d\n", i+1, score[i]);
- }
- return 0;
- }
复制代码核心规则:数组下标从0开始,长度为n的数组,下标范围0~n-1
6.2 二维数组
可理解为表格、矩阵,适合存储多行多列数据
- int arr[2][3] = {{1,2,3},{4,5,6}}; // 2行3列数组
复制代码七、函数(代码模块化)
函数是封装好的代码块,实现代码复用、简化逻辑,避免重复编写相同代码。C语言分为库函数(printf/scanf)和自定义函数。
7.1 函数语法结构
- 返回值类型 函数名(参数列表){
- // 函数逻辑
- return 返回值;
- }
复制代码7.2 自定义函数实战(求和函数)
- #include <stdio.h>
- // 自定义加法函数
- int add(int a, int b){
- return a + b; // 返回计算结果
- }
- int main()
- {
- int res = add(10, 20); // 调用函数
- printf("求和结果:%d", res);
- return 0;
- }
复制代码核心逻辑:main函数是程序入口,自定义函数需先定义、后调用,或提前声明。
八、指针(重点)
指针是 C 语言的核心难点,也是底层开发的核心。一句话通俗解释:指针就是专门用来存放内存地址的变量。普通变量存的是数据,指针变量存的是别的变量的内存编号(内存地址)。
8.1 核心符号
- &变量名:取地址运算符
读取变量在内存中的编号,得到该变量的内存地址,只能放在普通变量前面。 - *指针变量名:解引用(间接访问)运算符
根据指针保存的地址,找到这块内存,读写里面真实的数据。
注意:*有两个身份:定义指针时代表这是指针类型;使用时代表解引用,不要混淆。
8.2 指针基础实战
- #include <stdio.h>
- int main()
- {
- int a = 10; // 普通整型变量,内存里存数值10
- int *p = &a; // 定义int*类型指针p,把a的地址赋值给p
- printf("a的值:%d\n", a);
- printf("a的内存地址:%p\n", &a);
- printf("指针p里面存放的地址:%p\n", p);
- printf("指针p自己本身的地址:%p\n", &p);
- printf("*p解引用,拿到地址对应数据:%d\n", *p);
- *p = 66; // 通过指针修改a对应的内存,等价于 a = 66;
- printf("修改后 a = %d\n", a);
- return 0;
- }
复制代码结果:
核心作用:
- 修改外部变量:函数传参时传递地址,函数内部直接修改外面原始变量,不用拷贝一份数据。
- 高效操作数组:数组名本质就是首元素地址,指针可以遍历数组。
- 动态内存:配合malloc/free,在堆上手动申请、释放内存。
- 底层开发:访问硬件内存地址,写驱动、单片机、操作系统。
8.3 易错点
- int *p; 只定义指针,没有赋值,是野指针,直接*p程序直接崩溃。
- &只能作用于变量,不能写&10;
- 指针类型要匹配:int*只能存 int 变量的地址,不能接收 char 变量地址。
通俗类比:
变量 a 相当于房间,10 是房间里面的东西;
&a是房间门牌号;
指针 p 是一张纸条,纸条上写着门牌号;
*p就是拿着纸条上门牌号,打开房间,拿房间里面的东西。
九、结构体(自定义数据类型)
数组只能存储同类数据,结构体可以将不同类型的数据封装为一个整体,用于描述一个事物的完整属性(如学生、员工、商品)。
9.1 结构体代码
- #include <stdio.h>
- // 定义学生结构体
- struct Student{
- char name[20]; // 姓名
- int age; // 年龄
- float score; // 分数
- };
- int main()
- {
- // 定义结构体变量并赋值
- struct Student s1 = {"张三", 18, 92.5};
- printf("姓名:%s\n年龄:%d\n分数:%f", s1.name, s1.age, s1.score);
- return 0;
- }
复制代码十、完整代码示例
- #include <stdio.h>
- #include <string.h>
- // 定义图书结构体,图书ID、标题、作者和价格
- typedef struct {
- int id;
- char title[100];
- char author[50];
- float price;
- } Book;
- // 定义最大图书数量和图书数组
- #define MAX_BOOKS 100
- Book library[MAX_BOOKS];
- int bookCount = 0;
- // 增加图书的函数
- void addBook(Book newBook) {
- // 检查图书数组是否已满
- if (bookCount < MAX_BOOKS) {
- library[bookCount] = newBook;
- bookCount++;
- printf("图书添加成功!\n");
- } else {
- printf("图书库已满,无法添加新图书!\n");
- }
- }
- // 根据ID查找图书的函数
- void findBookById(int id) {
- for (int i = 0; i < bookCount; i++) {
- if (library[i].id == id) {
- printf("找到图书:ID = %d, 标题 = %s, 作者 = %s, 价格 = %.2f\n",
- library[i].id, library[i].title, library[i].author, library[i].price);
- return;
- }
- }
- printf("未找到指定ID的图书!\n");
- }
- // 根据ID删除图书的函数
- void deleteBookById(int id) {
- // 遍历图书数组
- for (int i = 0; i < bookCount; i++) {
- if (library[i].id == id) {
- for (int j = i; j < bookCount - 1; j++) {
- library[j] = library[j + 1];
- }
- bookCount--;
- printf("图书删除成功!\n");
- return;
- }
- }
- printf("未找到指定ID的图书,无法删除!\n");
- }
- int main() {
- int choice, id;
- Book newBook;
- while (1) {
- printf("\n图书信息管理系统\n");
- printf("1. 添加图书\n");
- printf("2. 查找图书\n");
- printf("3. 删除图书\n");
- printf("4. 退出系统\n");
- printf("请输入你的选择(1-4): ");
- scanf("%d", &choice);
- switch (choice) {
- case 1:
- // 输入新图书的信息
- printf("请输入图书ID: ");
- scanf("%d", &newBook.id);
- printf("请输入图书标题: ");
- scanf("%s", newBook.title);
- printf("请输入图书作者: ");
- scanf("%s", newBook.author);
- printf("请输入图书价格: ");
- scanf("%f", &newBook.price);
- addBook(newBook);
- break;
- case 2:
- // 查找
- printf("请输入要查找的图书ID: ");
- scanf("%d", &id);
- findBookById(id);
- break;
- case 3:
- // 删除
- printf("请输入要删除的图书ID: ");
- scanf("%d", &id);
- deleteBookById(id);
- break;
- case 4:
- // 退出
- printf("感谢使用图书信息管理系统,再见!\n");
- return 0;
- default:
- // 错误输入
- printf("无效的选择,请重新输入(1-4)。\n");
- }
- }
- return 0;
- }
复制代码十一、C语言常见报错
十二、学习总结与进阶路线
11.1 基础核心体系
程序运行流程 → 变量数据类型 → 输入输出 → 运算符 → 三大流程结构 → 数组 → 函数 → 指针 → 结构体
11.2 进阶学习方向
-
进阶语法:动态内存分配、枚举、联合体、预处理
-
底层核心:指针进阶、内存布局、文件操作
学习建议:C语言重实操,不要死记语法。每学一个知识点,就多尝试编写代码编译运行,通过报错调试理解底层逻辑。