编译过程:
编译器做了什么?1.预编译;2.编译;2.编译。
1.预编译:(不会报错)
处理所有注释,以空格代替
将所有的#define删除,并且展开所有的宏定义
处理条件编译指令#if,#ifdef,#elif,#else,#ednif
处理#include,展开被包含的文件
保留编译器需要使用的#pragma指令
指令:gcc -E file.c -o hello.i
2.编译:
对预处理文件进行一系列词法分析,语法分析和语义分析
词法分析主要分析关键字,标识符,立即数等是否合法
语法分析主要分析表达式是否遵循语法规则
语义分析在语法分析基础上进一步分析表达式是否合法
分析结束后进行代码优化生成相应的汇编代码文件
指令:gcc -S file.i -o hello.s
3.汇编:
汇编器将汇编代码转换成机器可以执行的指令
每个汇编语句几乎对应一条机器指令
指令:gcc -c file.s -o hello.o
对以下简单代码进行单步编译操作,打开每次生成的文件对比,进一步理解编译过程
// test.h
/*
This is the header file for test.c
*/
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
int g_global = 10;
// test.c
#include "test.h"
#define LOW 0
#define HIGH 255
int max(int a, int b)
{
return MAX(a,b);
}
int main()
{
int c = max(LOW, HIGH); // Call max to get the larger number
return 0;
}
链接器:
主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。
小结:
编译器将编译工作主要分为预处理,编译和汇编三部分。
连接器的工作是把各个独立的模块链接为可执行文件。
静态链接在编译期完成,动态链接在程序运行期完成。