在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
例如我们新建一个工程,包含list.h,list.c,test.c三个文件,这三个文件是如何变成计算机可以识别的二进制文件呢?
1、预处理:头文件的展开、宏替换、条件编译、去掉注释(list.i,test.i)
2、编译:检查语法,生成汇编语言(list.s,test.s)
3、汇编:汇编代码转换成二进制的机器码(list.o,test.o)
4、链接:将两个目标文件链接到一起
list.h文件
#include“stdio.h”
int add(int a,int b);
list.c文件
#include“list.h”
int add(int a,int b)
{
return a + b;
}
test.c文件
#include“list.h”
int main()
{
int ret = add(1,2);
printf(“%d ”,ret);
return 0;
}
一、以上三个文件经过预处理后
list.i文件
int add(int a,int b);
int add(int a,int b)
{
return a + b;
}
test.i文件
int add(int a,int b);
int main()
{
int ret = add(1,2);
printf(“%d ”,ret);
return 0;
}
二、编译检查程序是否有语法错误
test.s文件
int add(int a,int b);
int main()
{
int ret = add(?,?); //当前文件中没有add函数,add函数在list.s文件中,
printf(“%d ”,ret); //但有add的函数声明,编译可以通过
return 0;
}
三、转变成汇编语言
在C语言中:
倘若list.c文件中再有一个add函数
double add(double a,double b)
{
return a + b;
}
经过汇编后会得到两个<add>,add(1,2),add(1.0,2.0)。main函数中同时调用这两个add函数,因此在两个文件进行链接时,因无法分清add函数而导致传参时会发生冲突。
在C++中:
发现不是<add>,而是变成<Z3addii>,ii表示传入的两个参数类型为int。同样在定义同上的一个double类型add函数,在汇编过程会变成< Z3adddd>,因此在链接这两个文件过程中,main函数在同时调用这两个add函数时不会发生冲突。
即在C++编译器中,函数变成汇编语言时,会依据函数传参类型或顺序等不同而变成不一样的字符<Z3addii>,< Z3adddd>,C编译器则是直接将函数名拿来用<add>,<add>。