zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C语言入门——(第二讲——一个完整的程序结构)

C语言入门 一个 完整 第二 程序结构
2023-09-11 14:21:44 时间

讲述一个程序怎么变成一个软件(可执行文件)的。


1.一个完整的程序结构

        这里讲述的一个完整的程序是单文件的,也就是只有一个源文件,对于多文件的工程文件需要用到后面的预处理等才好讲述,这里从最简单的开始。一个程序要执行,就相当于你走路一样,是需要起点的,而C语言程序的起点就是main函数,并且你还需要包含一些必要的头文件。还是拿走路来说,可能你只是散步,你就只需要穿鞋,但如果你是登山,你就需要穿登山靴、带上地图、食物等一系列东西,你不可能自己去生产这些必需品吧,别人生产出来了你买就行了。对于编程一样,有一些常用的函数啊啥的都声明在头文件里面(注意是声明不是定义),函数要有实体,所以肯定光声明是不够用的,这就要涉及到动静态链接库了,你可暂且可以理解为你引用了头文件就可以用就行了,举个最简单的例子:

#include<stdio.h>  // 引入头文件(装备带上)
int main()         // 确定起点
{
    printf("hello c语言\n"); // 完成功能
    return 0;
}
// 至于int main()、return 0的具体含义,后面再细说,现在只需要知道怎么敲出一个完整的程序

        那么写好一个完整的代码了,程序怎么跑起来的呢?在讲程序怎么跑起来的之前先讲一下其他应用软件是怎么跑起来的。你肯定知道你的软件都是安装在你的某个磁盘当中的,计算机使用CPU计算处理数据。CPU的读写速度非常的快,但是保存数据的空间非常有限,而磁盘的读写速度就慢了很多,但是能够保存大量的数据。如果直接将磁盘中的数据传递给CPU,那CPU大部分时间都是在等待数据传输,极大地降低了效率。所以就利用了内存,内存能够存储一定量的数据,读写速度虽比CPU慢,但是比磁盘快。我们先将磁盘的数据加载到内存,然后内存再与CPU交换数据,这样就大大提高了效率,当然真实的情况还涉及到缓存和寄存器的更多知识,这里不细述,先了解个大概。举个生活中的例子,大家都知道做核酸,医护人员是相当地快,但是每次只能做一个,但是你从家里过去需要很长的时间,要是医护人员等做完一个再通知另外一个人从家里来,那不知道要什么时间才做得完,所以就有能够容纳一定数量的等候区,你们慢慢从家里赶来,医护人员一个一个给等候区的人做,这样没一会就做完了,虽然不是很恰当,但是应该能够体现一点这个思想。你启动软件的时候就是把应用程序加载到内存当中,然后再运行,这就是一般刚打开软件的时候有点慢的原因。  

        代码也是一样的,先由编译器和链接器转换成可执行文件(相当于一个软件了,这个在程序的预处理阶段再讲),然后加载到内存当中,最后再由CPU运算。当然,程序是一个比较广泛的概念,一般我们写的程序就是控制台程序,输出都在那个黑框,而比如一些软件是GUI程序,有很好看的交互界面。这里注意,C语言也是可以写GUI程序的,不要觉得C语言只会输出在那个黑框框里面,只不过C语言不适合开发或者说没那么多的轮子来辅助开发GUI程序。

2.源文件和头文件

        在开发软件的过程中,我们需要将编写好的代码(Code)保存到一个文件中,这样代码才不会丢失,才能够被编译器找到,才能最终变成可执行文件,这种用来保存代码的文件就叫做源文件。源文件其实就是纯文本文件,它的内部并没有特殊格式,源文件的后缀仅仅是为了表明该文件中保存的是某种语言的代码,相当于一种自描述,比如.c文件就是跟你说我是c语言程序哦,不是其他的程序,你别搞错了去用pycharm编译。我们经常写的代码实现都是在源文件里面的。

        头文件也就是.h文件,通常来讲,头文件只是一些变量和函数的声明,真正的函数实现是在源文件中的。主要是对于一些大工程,写在一起的话就太多了,对于大项目一般都是建立一个工程项目,把代码分门别类的放在不同的源文件和头文件中,方便了维护和管理。当然有时候还会有很多的音频文件、图片等,也是要放在同一个工程项目当中的。那你肯定会疑惑,我们使用库函数的时候,只引用了一个头文件,没有看到有具体的源文件啊,这就是那些源文件在动静态库当中,并没有展现出来,在编译(广泛的指源文件到可执行文件的全部过程)阶段就会悄悄和你自己写的代码组合的。

3.预处理、编译、汇编、链接

        我们写好程序就可以直接运行了吗?你会觉得点一下不就行了,其实没那么简单,还有很多事情是我们用的编译器悄悄执行的,虽然简化了步骤,但是不利于我们学习。一般来讲,从自己写好代码到可以运行会经历四个过程。

        第一步:预处理:预处理就是删除注释,拷贝头文件的实现、宏替换、条件编译等操作。因为那些注释是给人看的,对于计算机来说啥也不是!所以必须搞掉,不然占内存并且影响运行。

        第二步:编译:编译就是将C语言翻译成汇编语言,前面说了,计算机只认识0和1。那你肯定会想为啥不是搞成二进制指令呢,那是因为发明C语言的时候,已经有汇编了,肯定得站在巨人的肩膀上啊!至于汇编到二进制就不需要C语言操心了。

        第三步:汇编:汇编就是将汇编语言变成一种目标文件,这里就是汇编向二进制转化了。

        第四步:链接:链接其实就是一个“打包”的过程,它将所有二进制形式的目标文件和系统组件组合成一个可执行文件。 完成链接的过程需要一个特殊的软件,叫做链接器。为什么要和系统组件组合在一起呢?举个例子,你肯定知道输入输出函数,那是要从键盘读取数据和输出数据到显示器的,这就需要和硬件打交道,需要操作系统内核调动驱动器才可以操作一些硬件。这样叙述好像不太恰当,有些编译器对于一些函数是带有缓冲区的,并且每个编译器不一样,比如VS2019对于printf函数就没有配备缓冲,这细讲会很复杂,暂且不讲。

        在链接完之后,就变成可执行文件了,在windows系统下就是.exe文件,就跟一个软件没啥区别了,你编译完成之后在工程文件夹中找到那个可执行文件点开程序照样可以执行,但是你看不到源码,我们经常用的软件也就是这个道理。