1.程序的翻译环境和执行环境
在ANSI C的任何一种实现中,存在两个不同的环境
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令,也就是从,c文件到.exe文件;
第2种是执行环境,它用于实际执行代码;
翻译环境是由编译器提供的,而执行环境是由操作系统提供的。
如MSVC,DEV C++,Codeblocks这些编译软件都是集成开发环境,也就是集成了编辑,编译,链接和调试等功能。
2.详解编译和链接
2.1程序翻译环境下的编译和链接
从源文件到可执行程序可以分为编译和链接两步,在编译阶段源文件变成了目标文件,在链接阶段目标文件变成了可执行程序。
组成程序的每个源文件通过编译过程分别转化成目标文件;
每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序;
链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且链接器也可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
图解:
2.2深入编译和链接过程
编译本身可以分为预编译(预处理),编译和汇编。
预编译:在预编译阶段会将#include引用的头文件给输入到文件里面,进行#define定义的标识符的替换,以及将注释给删除,因为注释是给程序员看的,不是给电脑看的;
编译:在这个过程中会将C语言代码翻译成汇编代码,编译器会对代码进行词法分析,语法分析,语义分析,符号汇总;
汇编:会把在编译阶段形成的汇编代码翻译成二进制的指令,并将汇总的符号形成一个符号表;
在编译完成之后,就会开始链接,链接过程会合成段表,也就是将目标文件捆绑在一起,以及将符号表合并并进行重定位,最后生成可执行程序。
2.3运行环境
程序执行的过程:
1.程序必须载入内存中。在有操作系统的环境中,一般这个过程由操作系统完成,在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
2.程序开始执行,并调用main函数。
3.开始执行程序代码,这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址,程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程一种保留它们的值。
4.终止程序。正常终止main函数,也有可能是意外终止。
这里推荐一本书:《程序员的自我修养》,可以更加深层次的了解代码的编译和链接过程。
3.预处理详解
3.1预定义符号
预定义符号都是语言内置的
__FILE__ //进行编译的源文件
__LINE__ //当前代码的行号
__DATE__ //文件被编译时的日期
__TIME__ //文件被编译时的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
预定义符号的使用:
int main()
{
printf("file:%s\nline:%d\ndata:%s\ntime:%s\n", __FILE__, __LINE__, __DATE__, __TIME__);
return 0;
}
3.2#define
3.2.1#define定义的标识符
#define name stuff
举例:
#define MAX 1000
#define reg register //为 register这个关键字,创建一个简短的名字
#define do_forever for(;;) //用更形象的符号来替换一种实现
#define CASE break;case //在写c