别再瞎学 C 语言了!真・胎教级入门教程 | NO.1 万字详解C语言基础概念
C 语言看似简单,却是所有编程语言的基石,掌握它能极大提升编程思维.
进来看看这篇文章,我保证绝对不会让您失望.
追风赶月莫停留 平芜尽处是春山
从今天开始,我们将共同迈出攻克难关的第一步!
1. C语言是什么?
在现实生活中,人与人交流使用的是自然语言,如汉语 / 英语 / 日语等.
既然是学习计算机,那么人应该怎么与计算机交流呢? 答案是使用计算机语言.
迄今已知被创造的计算机语言已经有上千种了,人们是通过计算机语言写程序,给计算机下达指令,让计算机工作的.
而我们今天要了解的C语言就是众多计算机语言之中的一种,当然现在比较常用的C++ / Java / Go / Python 等也都是计算机语言.
2. C语言的历史和辉煌
C 语言由丹尼斯・里奇(Dennis Ritchie)在贝尔实验室,为开发 Unix 系统而设计,1972 年正式诞生.
下面是C语言的起源的发展历程,距今已有五十余年,可谓非常悠久:


而上方的人物就是C语言之父:丹尼斯·里奇(Dennis Ritchie)
3. 编译器的选择VS2026
3.1 编译和链接
C语言是一门编译型计算机语言,其源代码都是文本文件,而文本文件本身无法执行,因为计算机本身就只能理解二进制数字'0'和'1',必须通过编译器翻译和链接器的链接,生成二进制的可执行文件,这个可执行文件才能执行.
C语言的源代码是放在以.c为后缀的文件中的,要得到最终可运行的可执行程序,详细的中间要经历预处理(Preprocessing)→ 编译(Compilation,生成汇编代码.s)→ 汇编(Assembly,生成目标文件.o/.obj)→ 链接(Linking,生成可执行文件.out/.exe)四个过程.


⼀个工程⼀般都会有多个源文件组成,如下图所示,演示了源程序经过编译器和链接器处理的过程:

注:
1. 每个源文件(.c)单独经过编译器处理生成对应的目标文件(.obj为后缀的文件).
2. 多个⽬标⽂件和库⽂件经过链接器处理⽣成对应的可执⾏程序(.exe⽂件).
3.1.1详细过程:
(1). 预处理:
处理#开头的指令 / 删除代码中的注释.
最终输出 .i 为后缀的文件(纯C代码文本).
(2). 编译:
把C代码翻译成汇编语言.
语法检查 / 优化代码 / 生成汇编指令.
最终输出以 .s 为后缀的文件(汇编代码).
(3). 汇编:
把汇编代码翻译成机器码(二进制指令).
生成目标文件 / 只翻译当前文件,不处理外部函数.
输出文件: .o (Linux/macOS)或 .obj (Windows)
(4). 链接(Linking)
把多个目标文件 + 库文件(如 libc)合并.
解析函数调用(如 printf )/ 合并代码段、数据段 / 填充地址.
最终输出:可执行文件 Linux/macOS:无后缀 / a.out 或 Windows .exe

这就是在Windows电脑上C语言程序生成的exe可执行文件.
3.2 编译器的对比
C语言是一门编译型的计算机语言,需要依赖编译器将计算机语⾔转换成机器能够执⾏的机器指令。
那我们常⻅的C语⾔编译器都有哪些呢?
比如:msvc、clang、gcc就是⼀些常见的编译器,当然也有⼀些集成开发环境如:VS2022、VS2026 / XCode、CodeBlocks、DevC++、Clion等.
集成开发环境(IDE)⽤于提供程序开发环境的应⽤程序,⼀般包括代码编辑器、编译器、调试器
和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等⼀体化的开发软件服务套。
(1). VS2022集成了MSVC(安装包较大⼀些,安装简单,无需多余配置,使用起来非常方便)
(2). XCode集成了clang(苹果电脑上的开发⼯具)
(3). CodeBlocks集成了gcc(这个工具比较小众,需要配置环境,不太推荐)
(4). :Dev-C++ 是轻量级 IDE,集成 MinGW 版 GCC,适合入门 / 竞赛,但调试功能弱,不利于代码风格的养成,不适合大型项目.
(5). CLion 是跨平台 IDE,默认使用 CMake 构建系统,编译器可自由配(GCC/Clang/MSVC),适合中高级开发者,新手不推荐(配置门槛高)
整体考虑,推荐⼤家安装VS2022或VS2026的社区版本学习,免费,使用方便,工作中常见。
不懂得朋友可以在B站上搜索下载装配教程,在这里我推荐鹏哥C语言的教程,非常的胎教,简单易懂.
3.3 VS2022的优缺点
优点:
VS2022是⼀个主流的集成开发环境,企业中使⽤较为普遍
VS2022包含了:编辑器+编译器+调试器,功能强大
直接安装即可使用,基本不用额外配置环境,上⼿容易
默认界面是中文的,初学者友好
缺点:
功能丰富,安装包大,占用空间多。
4. VS项目和源文件、头文件介绍
在VS上写代码,我们是需要创建项⽬的,直接新建项⽬就可以了。
在项⽬中就可以添加源文件和头文件。
C语⾔把.c 为后缀的文件称为源文件,把.h为后缀的文件称为头文件。
头文件和源文件在VS中的展示
5. 第⼀个C语言程序
接下来让我们写出我们的第一个C语言程序"Hello World!",来向这个世界问好吧!
#include <stdio.h>
int main(void)
{
printf("Hello World!\n"); //在屏幕上打印"Hello World!"
return 0;
}
这⾥演示VS2026中创建项⽬和编写C代码的过程,并运行出结果。初学者不必死记硬背所有规则,开始学时只需要照猫画虎即可.模仿着学习,多敲代码、多观察运行结果,慢慢地就能熟练地自由运用了

在VS2026上运行代码的快捷键:ctrl + F5.
6. main函数
每个C语⾔程序不管有多少行代码,都是从main 函数(也叫做主函数)开始执行的
main 前⾯的int表示返回一个整型类型的值(数据类型会在之后详细讲解),所以在main 函数的最后写return 0,正好前后呼应.
注意:
(1). main 函数是程序的入口.
(2). main函数有且仅有⼀个,即使⼀个项⽬中有多个.c文件,也只能有一个main函数(因为程序的入口只能有⼀个).
第⼀次写代码,⼀些常⻅的错误总结:
(1). main被错写成了mian(或其他什么).
(2). main后边的()被漏掉了(这个括号像不像大门呢?正是程序的入口).
(3). 代码中不能使用中文符号,比如括号和分号,应全部使用英文符号.
(4). ⼀条语句结束后,应该有分号,表示该语句结束.
7. printf和库函数
7.1 printf函数
在上面有⼀句代码如下
printf("Hello Wrold!");
代码中使⽤了printf 函数,实现了在屏幕上信息的打印功能。
这⾥简单的介绍⼀下printf ,printf 是⼀个库函数,它的功能是在标准输出设备(⼀般指屏幕)上进行信息的打印。上面的代码是使用printf 函数打印字符串。只要把想要打印的⼀串字符放在双引号中传递给printf函数就可以将其打印在屏幕上。
不单单是字符串,printf函数也可以用来打印其他类型的数据,比如:
int n = 520;
printf("%d\n", n); //printf打印整型n
printf("%c\n", 'x'); //printf打印字符x
printf("%lf\n", 3.14); //printf打印双精度浮点型3.14
上面代码中的 %d / %c 等是占位符,在执行时会被后边的变量的值所替换.(后期会详细介绍)
7.2 库函数
同时我们在使用库函数的时候,是需要包含这个库函数所在头⽂件的,比如:printf函数和scanf函数是在stdio.h 这个头文件中的,而当我们想要使用这两个库函数时,就要在代码上方包含<stdio.h>,具体的方法就是:
#include <stdio.h>
1.那什么是库函数呢?
为了不再重复实现常见的代码,让程序员提升开发效率,C语⾔标准规定了⼀组函数,这些函数再由不同的编译器⼚商根据标准进⾏实现,提供给程序员使⽤。这些函数组成了⼀个函数库,被称为标准库,这些函数也被称为库函数.
在这个基础上⼀些编译器⼚商可能会额外扩展提供部分函数(这些函数其他编译器不⼀定⽀持).
⼀个系列的库函数⼀般会声明在同⼀个头⽂件中,所以库函数的使用之前,要包含其对应的头文件,库函数比较多,后期慢慢来介绍.
如果想提前了解可参考链接:https://cplusplus.com/reference/clibrary/ (里面有所有C语言可能会使用到的库函数).
8. 关键字介绍
C语⾔中有⼀批非常重要的保留的名字的符号,比如: int 、 if 、 return ,这些符号被称为保留字或者关键字.
(1).关键字都有特殊的意义,是保留给C语⾔使⽤的.
(2).程序员⾃⼰在创建标识符的时候是不能和关键字重复的.
(3). 关键字也是不能由自己创建的。
来自C89标准的C语⾔的32个关键字如下(也是最常用的):

注:在C99标准中加入了一些新的字,如inline 、 restrict 、 _Bool 等.
⼀些关键字大家可以去了解⼀下,不过使用最多的还是上面的32个关键字。
注:https://zh.cppreference.com/w/c/keyword(C语⾔关键字的全部介绍)有兴趣的自行了解.
9. 字符和ASCII编码
接下来来到一个比较有难度的部分了,我当时学的时候也觉得有点难以理解.
在键盘上可以敲出各种字符,如:a,q,@,#等,这些符号都被称为字符,C语⾔中字符是⽤单引号括起来的,如:'a','b','@'。
我们知道在计算机中所有的数据都是以二进制的形式存储的,那这些字符在内存中分别以什么样的⼆进制存储的呢?
如果我们每个人自己给这些字符中的每个字符编⼀个⼆进制序列,这个叫做编码,为了方便大家相互通信,不造成混乱,后来美国国家标准学会(ANSI)出台了⼀个标准ASCII编码,C语言中的字符就遵循了ASCII编码的⽅式。

我们不需要记住所有的ASCII码表中的数字,使用时查看就可以,不过我们最好能掌握几组特殊的数据:
(1). 字符A~Z的ASCII码值从65~90
(2). 字符a~z的ASCII码值从97~122
(3).对应的大小写字符(a和A)的ASCII码值的差值是32
(4).数字字符0~9的ASCII码值从48~57
(5). 换⾏\n 的ASCII值是:10
(6). 在这些字符中ASCII码值从0~31这32个字符是不可打印字符,无法打印在屏幕上观看
单个字符的打印可以使⽤%c来指定格式,也就是说,当我们使用%c的格式来打印时,如果在后面输入的是十进制的ASCII码值(当然也可换成八进制和十六进制),就可以打印( 不单单是打印)出其对应的字符.
这也就提到我们常说的一句话:在 C 语言里,字符的本质就是它对应的 ASCII 码值(整数)
#include <stdio.h>
int main(void)
{
printf("%c\n", 'Q');
printf("%c\n", 'X');
return 0;
}
int main()
{
int i = 0;
for (i = 32; i <= 127; i++)
{
printf("%c ", i);
if (i % 16 == 15)
printf("\n");
}
return 0;
}
故我们可以打印所有的可打印字符到屏幕上看看,代码如下:

10. 字符串和'\0'
C语⾔中如何表示字符串呢?使⽤双引号括起来的⼀串字符就被称为字符串,如:"abcdef",就是⼀个字符串。
C 语言中,用双引号包裹的字符串字面量,编译器会自动在末尾添加 '\0' 作为结束符;手动定义字符数组时,若不主动加 '\0',就不是合法的 C 语言字符串,printf 等函数会越界访问
字符串的打印格式可以使⽤%s来指定,也可以直接打印如下:
#include <stdio.h>
int main()
{
printf("%s\n", "hello World!");
printf("hello World!");
return 0;
}
C语言字符串中⼀个特殊的知识,就是在字符串的末尾隐藏放着⼀个 '\0' 字符,这个\0字符是字符串的结束标志。(这里很重要,要记清楚哦,后续的字符串数组如果用单引号 ' ' 来定义一个个字符的话可能要人为的在后方添加一个'\0'哦,不然可能会造成数组越界.
对于字符串"abcdef",我们实际上看到了6个字符:a,b,c,d,e,f,但是实际上在末尾还隐藏⼀个
转义字符 '\0' .
\0是字符串的结束标志。所以我们在使⽤库函数printf() 打印字符串或者使用strlen() 计算字符串⻓度的时候遇到 '\0' 就会自动停止了.
C语⾔中可以把⼀个字符串放在⼀个字符数组中,我们在这⾥利⽤下⾯的代码验证⼀下 '\0' 的作用:
#include <stdio.h>
int main()
{
char arr1[] = {'a', 'b', 'c'};//arr1数组中存放3个字符
char arr2[] = "abc"; //arr2数组中存放字符串
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
这样的代码,在调试的时候,观察⼀下arr1 和arr2 的内容


我们可以看到,arr1 字符数组在打印的时候,打印了a、b、c后还打印了⼀些随机值,这就是因arr1在末尾的地方没有\0字符作为结束标志,在打印的时候没有停⽌。但是arr2的打印就是完全正常的,就是因为arr2 数组是使⽤字符串常量初始化的,数组中有\0作为结束标志,打印可以正常停⽌。
如果我们在arr1数组中单独放⼀个'\0'字符会怎么样呢?

看到三次打印的结果是⼀样的了,都是打印到\0的时候就停⽌了,那从上述的例⼦我们确实能够观
察到\0的作用和重要性的。
11. 转义字符
11.1 定义及作用
也许在前⾯的代码中你看到 \n / \0 很纳闷是啥。其实在字符中有⼀组特殊的字符是转义字符,转义
字符顾名思义:转变原来字符意思的字符。
比如:我们有字符n,在字符串中打印的时候⾃然能打印出这个字符,如下:

如果我们修改⼀下代码,在n的前⾯加上\,变成如下代码:

我们可以看到修改的前后代码输出的结果,截然不同的,那这是为什么呢?
这就是转义字符的问题, \n 是⼀个转义字符表示换行的意思,我们可以简单的理解为 \ 让 n 的意思发生了转变, n 本来是⼀个普通的字符,被 \ 转义为换⾏的意思。
再例如如果我想在屏幕上打印内容: 龟叔说:"人生苦短,我学python" ,这时我们应该怎样处理呢?
如果我还像之前那样直接打印内容,请看效果:

这显然不能满足我的需求,因为计算机并不能充分了解你的意图,只能单纯的按照顺序分配双引号的使用,那么这时使用转义字符就可以实现我们的需求,请看:

11.2 代表性的转义字符
C语⾔中像这样的转义字符还有⼀些,具体如下:

下面是代码演示:
#include <stdio.h>
int main()
{
printf("%c\n", '\'');
printf("%s\n", "\"");
printf("c:\\test\\code\\test.c\n"); //题目一
printf("%s","D:\\MyFiles\\2025\\test.c\r\n") //题目二
printf("\a"); //是8
printf("%c\n", '\130'); //130是8进制,转换成10进制是88,以88作为ASCII码值的字符是'x'
printf("%c\n", '\x30'); //x30中的30是16进制,转换成10进制是48,以48作为ASCII码值的字符是'0'
return 0;
}
这些ASCII码值是可以自己写代码验证的,⼤家也可以自己验证。
关于转义字符我们首先要了解,然后要能在字符串中识别出来。
11.3 两道练习题
现在我们接着做两道题目来巩固一下知识点吧,看上方代码中的题目一和题目二,要求你分别数出它们之中字符串的长度
题目一:其中所有的 '\\' 都算作一个字符,可打印出字符 '\' , '\n' 算一个字符,表示换行.故它的长度为:20.
题目二: 除 '\\' 和 '\n' 外, 这里面还有一个转义字符 '\r' ,是回车符 ,故它的长的是24.
那么我上面给到的答案一定对吗?这是个值得思考的问题,这时回想起我在上面强调过的,使用双引号(" ")的字符串如果尾部没有 '\0' 的话,会自动在尾部加上 '\0'. 故所有上述答案应该在原有数值上再加一才是正确答案.是不是更加印象深刻了呢?
12. 语句和语句分类
C语⾔的代码是由⼀条⼀条的语句构成的,C语⾔中的语句可为以下五类:
• 空语句
• 表达式语句
• 函数调⽤语句
• 复合语句
• 控制语句
12.1 空语句
空语句是最简单的,⼀个分号就是⼀条语句,是空语句。
#include <stdio.h>
int main()
{
;//空语句
return 0;
}
空语句在语法上是一条完整语句,常用于循环或条件判断中充当循环体,表示 “暂时什么都不做”。例如在需要延时、占位,或者后续再补充逻辑的场景中,使用空语句可以避免语法报错。但随意使用空语句也可能造成逻辑错误,比如多写了一个分号导致循环体提前结束。
12.2 表达式语句
表达式语句就是在表达式的后边加上分号。如下所示:
#include <stdio.h>
int main()
{
int a = 20;
int b = 0;
b = a + 5; //表达式语句
return 0;
}
12.3 函数调⽤语句
函数调用的时候,也会加上分号,就是函数调⽤语句。
#include <stdio.h>
int Add(int x, int y) //加法函数
{
return x+y;
}
int main(void)
{
printf("hehe\n");//函数调⽤语句
int ret = Add(2, 3);//函数调⽤语句
return 0;
}
12.4 复合语句
复合语句其实就是代码块,成对括号中的代码就构成⼀个代码块,也被称为复合语句。
#include <stdio.h>
void print(int arr[], int sz) //函数的⼤括号中的代码也构成复合语句
{
int i = 0;
for(i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
int i = 0;
int arr[10] = {0};
{
for(i = 0; i < 10; i++) //for循环的循环体的⼤括号中的就是复合语句
arr[i] = 10 - i;
printf("%d\n", arr[i]);
}
return 0;
}
12.5 控制语句
控制语句⽤于控制程序的执行流程,以实现程序的各种结构⽅式(C语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。
可分成以下三类:
1. 条件判断语句也叫分⽀语句:if语句、switch语句;
2. 循环执⾏语句:dowhile语句、while语句、for语句;
3. 转向语句:break语句、goto语句、continue语句、return语句。
这是C语言中非常重要的内容,需要着重学习,这里就先不给出范例,后期会给⼤家⼀⼀介绍控制语句。
13. 注释是什么?为什么写注释?
注释是对代码的说明,编译器会自动忽略注释,也就是说,注释对实际代码没有影响。
注释是给程序员自己,或者其他程序员看的。
好的注释可以帮我们更好的理解代码,但是也不要过度注释,不要写没必要的注释。
当然不写注释可能会让后期阅读代码的⼈抓狂。
写注释⼀定程度上反应了程序作者的素质,建议⼤家写必要的注释,在未来找工作的时候,写代码时
留下必要的注释也会给面试官留下更好的印象。
注释不是多余的,它是代码的说明书,也是未来你回看程序时最好的提示
13.1 注释的2种形式
13.1.1 /**/ 的形式
第⼀种⽅法是将注释放在/*...*/ 之间,内部可以分行。
/* 注释 */
/*
这是⼀⾏注释
*/
这种注释可以插在行内。
int fopen(char* s /* file name */, int mode);
上⾯示例中,/* file name */ ⽤来对函数参数进行说明,跟在它后⾯的代码依然会有效执行。
这种注释⼀定不能忘记写结束符号*/,否则很容易导致错误.
printf("a "); /* 注释⼀ 就在这里本应该有一个结束的标志
printf("b ");
printf("c "); /* 注释⼆*/
printf("d ");
上面示例的原意是,第⼀行和第三行代码的尾部,有两个注释。
但是,第⼀行注释忘记写结束符号,导致注释⼀延续到第三行结束。/**/ 的这个注释也不⽀持嵌套注释,/* 开始注释后,遇到第⼀个*/就认为注释结束了。
13.1.2 // 的形式
第二种写法是将注释放在双斜杠// 后面,从双斜杠到行尾都属于注释。
这种注释只能是单行,可以放在行首,也可以放在⼀行语句的结尾。这是C99标准新增的语法.
// 这是⼀⾏注释
int x = 1; // 这也是注释
13.1.3 注意事项
不管是哪⼀种注释,都不能放在双引号里面。
双引号里面的注释符号,会成为字符串的⼀部分,解释为普通符号,失去注释作⽤。
printf("// hello /* world */ ");
上⾯示例中,双引号内的//和/* */都会被当作普通字符,不会被解析为注释,因此整行都会被打印,不会被预处理删除.
13.2 注释会被替换
预处理阶段会删除注释,将注释内容替换为一个空格 ,因此 min/*这里是注释*/value 会被处理为min value,而非minvalue,避免了标识符拼接错误.
14.结语
学习 C 语言的过程,本质上是学习计算机如何思考的过程。它不像一些高级语言那样封装了大量细节,反而会让你直面内存、地址、指令等底层逻辑。
也许刚开始你会觉得语法繁琐、报错不断,但只要坚持敲完每一个示例、弄懂每一个报错原因,你会逐渐发现:C 语言简洁、高效、强大,它能带你真正走进编程的大门,为后续学习 C++、数据结构、算法、操作系统、嵌入式开发打下最坚实的基础。
希望这篇文章能成为你 C 语言学习路上的起点,也期待你写出越来越多优秀的代码.
那么本文章就到此结束. 码字不易,如果觉得我写的还可以,还请多多点赞和收藏(人工狗头).
如果觉得所写内容对您有些许帮助,或许可以关注一下 持续更新.
C语言之后篇章的内容详解也会定期更新,敬请期待.
菜鸟一枚,如有错误还请不吝赐教,关于文章表达形式的建议也请直接告知我.
正在学习中,你我共勉,无限进步!
2026. 4.5
---14:56
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)