【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)-1

简介: 【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)-1

1.程序的翻译环境和执行环境

总体过程:


76371bc13ab24ec89e28b2656bd1f54a.png


在ANSI C的任何一种实现中,存在两个不同的环境


第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
第2种是执行环境,它用于实际执行代码。

2.翻译环境(编译+链接)

我们常说一个test.c文件要经过以下步骤才能产生可执行的程序,那么具体是怎么做到的呢?

ceb79e5870b84e028c90ba67b33d0a3a.png



在vs编译器上是要经过以下过程的:


8e9a459e1beb447d95a6835f7ae0e2bd.png


源文件和目标文件的关系:

94191843c70e48f986bd82a033942985.png



       VS是一个集成开发环境,集成很多的功能ctr1+F5,不方便观察每个细节的功能接下来,我使用gcc这个编译器给大家演示


9856e52cde9f4e38ab9663aa1f829bd9.png


       由于上图的操作把这个编译运行的步骤一次走完了,我们一步步来,咱们用指令让程序停在预编译的阶段:



a63c4db0cde04f6290eafe1b3ea71ac6.png

编译(编译器)

预编译(预处理)

将控制台的内容放到test.i之后,预处理阶段所做的事情:


1.头文件的包含


616e930f7631428c8d506d7e546a135c.png

2.注释的测试


df65241e22764915ae6f468c5bd385ad.png

编译过程

功能:把C语言代码翻译成汇编代码

经历四个过程:涉及一门课 -- 《编译原理》

1.语法分析
2.词法分析
3.语义分析
4.符号汇总
函数名,全局变量, 不会汇总 局部变量(函数运行起来才行)


dad3ff1069f2443eacd7eee801cacc45.png


编译阶段所做的事情,gcc操作过程:


47a01b0bf5154f3086d3f70c6e092bce.png

汇编过程

1.把汇编代码转换成二进制的指令



47be8961a2fd420da7edd20cad1fd0b1.png

2.形成符号表

61f630e8047244cbb0538ef431ab4c1e.png



链接

1.合并段表
2符号表的合并和重定位
1、2的作用其实是在链接期间为这种跨文件的代码进行协作的时候起作用的。


在vscode中操作:


249aec60b20643dd9104203eab97eac0.png


过程:


67444a12d8094a44bf625dca1484263e.png


1.合并段表


0b1a9312d81b47f785b28b746da241db.png

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

       把无效的地址给替换掉,符号表和段表的关系是:符号表是段表的内容



ab530775f9dc410d8a501be3442f56d2.png

那该如何体现这个作用呢?


       假设我们在test.c文件底下extern了一个函数Add,但是在add.c底下没有实现这个Add函数,就会输出以下错误(链接型错误)


63039f86d03b40e0b752243763c8e73a.png


       如果说这个函数写错的话,在main函数内调用大写的,但是在add.c内定义成小写的,是依然找不到


805208c9efd044beb9e9dfef2569c6a2.png


计算机语言的发展

2b4a50ad6ce2432180bcfc9286f37cd5.png


运行环境(翻译之后)

🔍程序执行的过程:

1. 程序必须载入 内存 中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2. 程序的执行便开始。接着便调用 main 函数(main函数第一行开始)
3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈( stack )-- 函数栈帧 ,存储函数的局部变量和返回地址。 程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4. 终止程序。正常终止 main 函数;也有可能是意外终止。

3.预处理详解

3.1 预定义符号

这些预定义符号都是语言内置的。

__FILE__       //进行编译的源文件
__LINE__     //文件当前的行号
__DATE__     //文件被编译的日期
__TIME__     //文件被编译的时间

执行:

6362de3b3ffd4a1fb2639f2a2ccdcae3.png



这个预定义符号也是语言内置的

__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义



7bad5a774aef4099a768379dae871e9b.png

而放在gcc编译器上面是可以执行通过的:


9a12e050f8704aaf9f5fd396a1be9c08.png


       编译器在代码编译的时候,会对函数和变量名重命名的,C++ 中会更加复杂


       在C语言中重命名的规则基本就是:加_


33dfd27fca3a4573a06f9eb7a881440e.png



【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)-2

https://developer.aliyun.com/article/1456981

相关文章
|
7月前
|
存储 编译器 程序员
程序环境和预处理
程序环境和预处理
|
7月前
|
存储 编译器 程序员
零基础也能学会的『程序环境和预处理』
零基础也能学会的『程序环境和预处理』
|
存储 编译器 程序员
程序环境和预处理 - 带你了解底层的的编译原理
程序环境和预处理 - 带你了解底层的的编译原理
104 1
|
编译器 Linux C++
【程序环境与预处理】(二)
【程序环境与预处理】(二)
88 0
|
7月前
【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)-2
【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(上)-2
|
7月前
|
编译器 Linux C++
【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(下)
【C进阶】C程序是怎么运作的呢?-- 程序环境和预处理(下)
|
7月前
|
编译器 Linux C++
【程序环境与预处理玩转指南】(下)
【程序环境与预处理玩转指南】
|
7月前
|
存储 编译器 程序员
【程序环境与预处理玩转指南】(上)
【程序环境与预处理玩转指南】
|
存储 自然语言处理 编译器
|
自然语言处理 算法 程序员
【C语言技能树】程序环境和预处理
在ANSI C的任何一种实现中,存在两个不同的环境。
128 0