【C语言】详细介绍程序环境,预处理,编译,汇编,链接,其中预处理阶段重点讲解
目录
程序环境
翻译环境
1. 翻译环境的两个过程
2. 编译过程的三个阶段
执行环境
预处理(预编译)
1. 预定义符号
2. #define
2.1 用 #define 定义标识符(符号)
2.2 用 #define 定义宏
2.3 #define 的替换规则
2.4 # 和 ## 的用法
2.5 宏和函数
2.6 #undef
3. 命令行定义
4. 条件编译
5. 文件包含
5.1 两种头文件的包含
5.2 嵌套文件包含
1. 程序环境
在ANSI C(标准C)的任何一种实现中,存在两个不同的环境。
1. 翻译环境:在这个环境中源代码被转换为可执行的机器指令。
2. 执行环境:它用于实际执行代码。
C语言代码是文本信息,计算机不能直接理解,计算机是执行二进制指令的。
翻译环境负责将C语言代码转成二进制指令,执行环境负责执行二进制指令。
1.1 翻译环境
1.1.1 编译与链接
翻译环境分为编译与链接两个过程。
1. 一个工程可以有多个.c(源文件),每个源文件都会单独经过编译器处理生成自己对应的目标文件(.obj),这个过程叫做编译。
2. 多个目标文件和链接库经过链接器的处理,最后生成可执行程序,这个过程叫做链接。
链接库的意思是链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
1.1.2 预处理,编译,汇编
翻译环境分为编译和链接两部分,编译又有预处理,编译,汇编三个阶段。
1. 预处理:gcc -E test.c -o test.i
预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。
2. 编译:gcc -S test.c
编译完成之后就停下来,结果保存在test.s中。
3. 汇编:gcc -c test.c
汇编完成之后就停下来,结果保存在test.o中。
符号
1. 查看符号,这些符号都是全局的。
2. 每个源文件自己编译阶段符号汇总,汇编阶段形成符号表(符号,对应地址),链接进行所有源文件的符号表合并(相同符号合并,函数定义的符号的地址为有效地址,函数声明的符号的地址为无效地址,选取有效地址)。
比如:下图main.c符号表中_sum地址是无效的,合并的时候选择sum.c符号表的_sum地址。
1.2 执行环境
程序执行的过程:
1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排(例如单片机的烧录),也可能是通过可执行代码置入只读内存来完成。
2. 程序的执行便开始。接着便调用main函数。
3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack)也就是函数栈帧,存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
4. 终止程序。正常终止main函数;也有可能是意外终止。
2. 预处理(预编译)
2.1 预定义符号
以下预定义符号会在预处理阶段被替换。
__FILE__ 替换为当前进行编译的源文件名称
__LINE__ 替换为当前的行号
__DATE__ 替换为文件被编译的日期
__TIME__ 替换为文件被编译的时间
__STDC__ 如果编译器遵循ANSI C,其值为1,否则未定义
.