程序的环境和预处理

  • 1.程序的环境
      • 预编译
        • 1.头文件的包含
        • 2.#define的预处理指令的执行
        • 3.注释的删除
      • 编译
      • 汇编
      • 链接
      • 运行

1.程序的环境

写过无数代码的你是否想过你写的.c文件编译链接运行形成.exe文件的中间是怎样执行的吗?
从.c文件到.exe文件到代码的执行,这就是过程。
程序的环境和预处理_第1张图片

.c文件我们叫做源文件,是文本文件,.exe文件是可执行文件,是二进制文件,是机器能够读懂的文件。
在.c文件编译链接形成.exe文件的环境我们成为编译环境,.exe执行的环境我们称为运行环境
编译环境又可以分为编译链接两个过程。而编译过程又可以分为预编译编译汇编三个过程。
程序的环境和预处理_第2张图片
我们的代码进行编译所需要的工具是编译器,例如VS2013等等编译器。
我们每一个源文件(.c),头文件(.h)都是通过编译器(vs编译器下的编译器是cl.exe)单独编译生成目标文件(.obj)最后通过链接器(vs编译器下的链接器link.exe)形成可执行程序。这就是编译的过程。我们接下来分为三个小步来具体解析编译的过程。
程序的环境和预处理_第3张图片

程序的环境和预处理_第4张图片
当我们走到这里,我们用vs观看就已经不再直观,我们要使用Linux下的编译环境用gcc编译器观看会更加的直观。所以接下来的操作都是在Linux环境下进行操作的。如果对Linux编译环境有兴趣的,可以点击下面一个链接能够让你轻松入门Linux。

Linux轻松入门

预编译

1.头文件的包含

程序的环境和预处理_第5张图片
这是我们在Linux环境下写的代码。然后执行 gcc test.c -E -o test.i

程序的环境和预处理_第6张图片
执行后,代码前面少了#include,多了一大串其实的实际代码。当我们把#include去掉后再执行
gcc test.c -E -o test.i
程序的环境和预处理_第7张图片
可以清晰的看到代码少了很多。

2.#define的预处理指令的执行

将#define定义的代码直接替换掉

程序的环境和预处理_第8张图片
编译之后的结果:
程序的环境和预处理_第9张图片

3.注释的删除

我们进行的注释在预编译是直接删除掉的。
程序的环境和预处理_第10张图片

编译之后的结果:
程序的环境和预处理_第11张图片

编译

编译的过程是将我们的C语言代码编译成了汇编代码。
这其中包括:
1.词法分析
2.语法分析
3.语义分析
4.符号汇总
这门课程叫做《编译原理》有兴趣的同学可以自己学习。
在Linux操作系统下的操作是
gcc test.i -S
这样就会生成一个test.s的文件

程序的环境和预处理_第12张图片

汇编

汇编就是把汇编代码转换成二进制指令(机器指令)
再一个就是形成符号表。
Linux下的操作是
gcc test.s -c
这样就生成了一个test.o的二进制文件
相当于是VS编译下形成的test.obj 文件
如图是一段我们看不懂的指令,其实.obj文件的格式是elf格式,在Linux下输入指令readelf就能实现相应的操作。
程序的环境和预处理_第13张图片

链接

1.合并段表

Linux指令
readelf test.o -a
程序的环境和预处理_第14张图片

2.符号表的合并和重定向
就是每个文件都有自己的符号表,合并和重定位就是将所有的符号汇总,例如在另外一个文件声明定义的函数,在这个文件中使用。总体来说就是链接所有的文件。

运行

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

谢谢大家!!!!!

你可能感兴趣的:(笔记,c++)