C语言的程序环境

文章目录

    • 一.前言
    • 二.编译环境
    • 2.1预处理阶段
    • 2.2编译阶段
    • 2.3汇编阶段
    • 2.4链接阶段
    • 三.运行环境

一.前言

在ANSI C的任何一种实现中,存在两个不同的环境
1.翻译环境,在这个环境中源代码被转换为可执行的机器指令.
2.执行环境,它用于实际执行代码.

二.编译环境

C语言的程序环境_第1张图片
我们每写完一个C语言代码,在编译的时候都会先经过编译环境把它变成可执行程序
但是编译环境还要分成几个步骤:
预处理(预编译),编译,汇编,链接
C语言的程序环境_第2张图片

这四个步骤需要用到两个工具才能实现:编译器,链接器
C语言的程序环境_第3张图片
预处理–汇编阶段都叫编译。

当然我们再写代码的时候,不可能只有一个.c文件。再写多个.c文件后在编译:
C语言的程序环境_第4张图片

每个.c文件通过编译器形成相对应的目标文件,然后所有的目标文件+链接库通过链接器形成可执行程序
这些.c文件,目标文件在我们创建的工程里都是可以看到的
C语言的程序环境_第5张图片

在运行.c的过程虽然很复杂,但是我们有很多可以用的IDE,比如我现在用的VS2022。
可能会有人想什么是IDE?IDE是集成开发环境
我们刚刚提到的编译器(el.exe),链接器(link.exe),还有编辑器,调试器。我们用到的IDE就是帮我们把这些封装在了一起,我们调试,运行的时候直接用就行。

2.1预处理阶段

我们程序在预编译之后会发生什么呢?

  1. 头文件的包含。我们再写代码的时候,像stdio.h,stdlib.h这些头文件肯定都会用到。所以在预编译之后,就把这些头文件里的内容全部放进去。
  2. 注释的消除。我们在写代码的时候会有写注释的习惯,我们也知道这些注释,是根本不会被运行的,那是因为注释在预编译的时候已经消掉了。
  3. #define符号的替换。我们用到的宏定义也会被替换到程序中。

2.2编译阶段

编译阶段是把C语言代码转换成汇编代码
然后在进行几个步骤:

语法分析
词法分析
语义分析
符号汇总

这里我主要带你们认识一下符号汇总:

每个.c文件都或多或少用到函数,变量。
符号汇总就是把每个.c程序里用到的函数名全局变量名都各自汇总在一起。这就是符号汇总。

2.3汇编阶段

  • 汇编指令转化成二进制指令
  • 形成符号表

什么是符号表?
我们在编译的环节有一个符号汇总,就是把所有函数名,全局变量名字放到一起。
符号表,你可以认为是这个样子的
C语言的程序环境_第6张图片
就是每个文件都会有这样的一个表。具体有什么用,一会在链接的地方就可以体现出来了
这里有个要注意的点,text.c和Add.c都有Add.c函数,但是在Add.c文件中Add函数是有一个固定的地址的。但是在text.c文件里我们只是声明了一下,地址也是随机的。

2.4链接阶段

  1. 合并段表
  2. 符号表的合并和重定位

合并段表
我们刚才讲过在编译阶段结束后会生成一个.obj的目标文件(linux环境下生成的是.o文件)。这个目标文件它是elf文件格式的。
就是它这个文件里的内容是分成几个部分存放的:
C语言的程序环境_第7张图片
合并段表,就是把每个.c文件形成的.obj文件各自的部分全部合成一起,形成一个新的文件
C语言的程序环境_第8张图片

符号表的合并和重定位:
在汇编阶段,每个文件都会形成一个符号表,但是我们text.c里的Add只是声明了一下,地址也是随机的,没有意义。
所以我们在合并的时候会重定位,将Add.c里的Add函数当成新的符号表的内容。
合并好之后,程序就可以在运行的时候通过各自函数的地址来找到对应的函数。

如果我们没有Add这个函数会怎么样?
C语言的程序环境_第9张图片
你看就会报一个错误无法解析外部符号,而且是从LNK2019这里报的,就是说在链接这块出现了问题。

我们看:
C语言的程序环境_第10张图片
发现在链接的过程中好像还有一个东西–>链接库。
链接库就是我们引入的外部的那些函数所用到的库,我们把链接库也一起添加上才能知道我们用到的函数的具体位置。

三.运行环境

程序执行的过程:

  1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成,像单片机,你就需要把写好的代码烧到单片机里去。
  2. 程序的执行便开始。接着便调用main函数。
  3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。关于这一步想要了解的可以看看这个->函数栈帧的创建与销毁。
  4. 终止程序。正常终止main函数;也有可能是意外终止。

你可能感兴趣的:(C语言,c语言)