目录

gcc、g++

c语言的##和#

##表示把两个宏参数贴合在一起,而单个#的功能是将其后面的宏参数进行字符串化操作。

gcc、g++命令

  1. -E 预处理

  2. -S 预处理,编译

  3. -c 预处理,编译,汇编

  4. 链接器ld链接

  5. -o 输出文件

gcc -E filename.c -o filename.i 将c文件转化成C++文件,这个过程也叫做预处理过程。

gcc -S filename.i -o filename.s 将预处理过程生成的.i后缀的文件转化成汇编文件,里面存储的是相应的汇编代码,这个过程叫做编译。

gcc -c filename.s -o filename.o 将汇编文件中的汇编代码翻译成相应的机器语言,这个过程叫做汇编。

gcc filename.o -o filename.exe 这条指令是完成链接这个过程的,它通过链接器ld将运行程序的目标文件和库文件链接在一起,生成最后的可执行文件。 生成可执行文件后,我们就能够调用相应的程序了。

gcc -c编译后,没有声明的func函数不会报错,会输出对应.o文件 gcc 链接后,只要所有.o文件中有这个func,就会成功

gcc和g++的区别

编译c程序

熟悉C++的人应该都知道,C++是C语言的超集,编写C/C++代码的时候,有人用gcc,也有人用g++,我们先来看看gcc和g++是否都能编译C++和C代码:

上图中,我们发现用gcc和g++分别编译test.c这个c文件,发现都是可执行的,实际上对于C文件gcc和g++所做的事情确实是一样的,g++在编译C文件时调用了gcc.

编译cpp程序

既然二者对c程序来说都一样的,那为什么两者都存在而不是只存在一个呢,不要着急,下面我们来看看他们分别是如何来编译C++程序的. 首先我们直接编译c文件生成可执行程序:

我们发现gcc报错,而g++没有报错,并且可以执行。

下面我们来看看它们的具体步骤以及错误原因:

  1. 预处理

在预处理阶段两条命令都能够成功,并且我们观察gcc和g++各自产生的.i后缀的文件,它们的内容都是相同的,所以我们能够发现gcc和g++在cpp程序中它们做了相同的事情。

  1. 编译

我们发现gcc编译test1.i(.cpp生成)的会出现大篇幅的错误,图片中的错误主要是说无法找到cout函数的库文件,而g++去可以通过编译并且生成汇编文件,这件事情说明gcc无法自动和c++的库文件进行连接,导致了库函数没有申明的错误.

  1. 汇编

这个过程应该都没有问题,因为这个过程只是将后缀为.s文件中的汇编语言转换成了相应的机器语言。所以gcc和g++应该在这个过程中做了同样的事情。 4. #### 链接

这个阶段也出现了问题,用gcc将.cpp后缀产生的.o文件转换成可执行文件时出现了错误,而g++却可以转换成功并且能够正确执行。这个还是因为gcc无法将库文件与.o后缀的文件关联在一起生成可执行程序,而g++可以完成这项工作。

总结

gcc和g++的区别主要是在对cpp文件的编译和链接过程中,因为cpp和c文件中库文件的命名方式不同,那为什么g++既可以编译C又可以编译C++呢,这时因为g++在内部做了处理,默认编译C++程序,但如果遇到C程序,它会直接调用gcc去编译.

#include 其实就是展开 extern “C”{} 表示用C编译器来编译 c调用c++就用extern “C"把c++的.h包起来,这样.c中include c++头文件的时候就会用c的方式编译

1
2
3
4
5
6
7
8
#ifdef __cplusplus
extern "C"
{
#endif
//被c调用部分
#ifdef __cplusplus
}
#endif

C++编译器可以兼容并编译C语言,但优先使用C++编译方式,extern关键字让C++编译器使用C语言编译方式编译

  1. C++编译器不可以以c方式编译重载函数。
  2. C++编译方式将函数名和参数列表作为目标名。
  3. C编译方式将函数名作为目标名。 因为C只有单一的命名空间,不支持函数重载之类的特性,例如对于函数void fun(int a, int b),经过编译后生成的符号为fun, C链接器链接的时候就会去找fun这样的函数符号;C++为了支持函数重载(即函数名字可以相同,参数类型或个数不同),允许存在同名的函数,这一点在C中是做不到的。其实,C++甚至可以存在相同的类型、变量等,因为在C++中命名空间的存在。在C++中,对于函数void fun(int a, int b),经过编译后,生成的类似为_fun_int_int, 新生成的符号名不仅带有函数名,还有参数类型。正因为他们两者编译函数的时候,生成的符号规则不一样,所以,在混合编程中,如果我们不进行任何处理,而相互效用的话,必然会出现在链接的时候,找不到符号链接的情况。 为实现混合编程,我们不得不提到extern “C” , extern “C"是C++的特性,是一种链接约定,通过它可以实现兼容C与C++之间的相互调用,即对调用函数能够达成一致的意见,使用统一的命名规则,使得实现方提供的接口和调用方需要的接口经按照指定规则编译后,得到的都是一致的函数符号命名。