1.程序的环境
写过无数代码的你是否想过你写的.c文件编译链接运行形成.exe文件的中间是怎样执行的吗? 从.c文件到.exe文件到代码的执行,这就是过程。 
.c文件我们叫做源文件,是文本文件,.exe文件是可执行文件,是二进制文件,是机器能够读懂的文件。 在.c文件编译链接形成.exe文件的环境我们成为编译环境,.exe执行的环境我们称为运行环境。 而编译环境又可以分为编译和链接两个过程。而编译过程又可以分为预编译,编译,汇编三个过程。  我们的代码进行编译所需要的工具是编译器,例如VS2013等等编译器。 我们每一个源文件(.c),头文件(.h)都是通过编译器(vs编译器下的编译器是cl.exe)单独编译生成目标文件(.obj)最后通过链接器(vs编译器下的链接器link.exe)形成可执行程序。这就是编译的过程。我们接下来分为三个小步来具体解析编译的过程。 
 当我们走到这里,我们用vs观看就已经不再直观,我们要使用Linux下的编译环境用gcc编译器观看会更加的直观。所以接下来的操作都是在Linux环境下进行操作的。如果对Linux编译环境有兴趣的,可以点击下面一个链接能够让你轻松入门Linux。
Linux轻松入门
预编译
1.头文件的包含
 这是我们在Linux环境下写的代码。然后执行 gcc test.c -E -o test.i
 执行后,代码前面少了#include<stdio.h>,多了一大串其实的实际代码。当我们把#include<stdio.h>去掉后再执行 gcc test.c -E -o test.i  可以清晰的看到代码少了很多。
2.#define的预处理指令的执行
将#define定义的代码直接替换掉
 编译之后的结果: 
3.注释的删除
我们进行的注释在预编译是直接删除掉的。 
编译之后的结果: 
编译
编译的过程是将我们的C语言代码编译成了汇编代码。 这其中包括: 1.词法分析 2.语法分析 3.语义分析 4.符号汇总 这门课程叫做《编译原理》有兴趣的同学可以自己学习。 在Linux操作系统下的操作是 gcc test.i -S 这样就会生成一个test.s的文件

汇编
汇编就是把汇编代码转换成二进制指令(机器指令) 再一个就是形成符号表。 Linux下的操作是 gcc test.s -c 这样就生成了一个test.o的二进制文件 相当于是VS编译下形成的test.obj 文件 如图是一段我们看不懂的指令,其实.obj文件的格式是elf格式,在Linux下输入指令readelf就能实现相应的操作。 
链接
1.合并段表
Linux指令 readelf test.o -a 
2.符号表的合并和重定向 就是每个文件都有自己的符号表,合并和重定位就是将所有的符号汇总,例如在另外一个文件声明定义的函数,在这个文件中使用。总体来说就是链接所有的文件。
运行
- 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序
的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。 - 程序的执行便开始。接着便调用main函数。
- 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回
地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程 一直保留他们的值。 - 终止程序。正常终止main函数;也有可能是意外终止。
谢谢大家!!!!!
|