gcc和g++有什么区别?一篇文章带你彻底搞清楚

tmyb

折腾了这么多年代码,我总算把这哥俩给弄明白了。

以前我在那家做通信协议的老东家干活时,组里有个带我的老师傅,特别较真。有次我写了个简单的C++打印程序,顺手在终端里敲了个gcc *,结果屏幕上蹦出一大串报错,全是些看不懂的链接错误。老师傅走过来瞅了一眼,没说话,直接把命令改成了g++ *,代码竟然就这么跑通了。当时我脸红得跟猴屁股似的,心里直犯嘀咕:这gcc和g++不都是编译器吗?怎么差这么多?

这事儿得从它们的“底子”说起。

我后来为了搞清楚这事,专门翻了GNU的文档,还自己动手做了几组实验。大家伙儿得先记住一点:gcc不是指某一个具体的编译器,它是一套编译器集合。在这个大筐子里,有处理C语言的,有处理C++的,甚至还有处理Java和Ada的。而g++,它是这套集合里专门负责C++的那个“带头大哥”。

我在实践中发现,如果你拿它们来编译一个后缀是.c的文件,区别就开始显现了:

  • 处理逻辑不同:gcc会把.c文件老老实实当成C语言看,但g++不管三七二十一,只要是你喂给它的文件,它统一按C++的规矩来办。
  • 预定义的宏不一样:用g++编译的时候,它会自动给你加上一堆C++特有的宏定义。我以前在代码里写过一些根据编译器环境切换逻辑的宏,结果用gcc编译.c文件时死活不生效,换了g++就全现原形了。
  • 链接库才是重头戏:这是最坑的一点,也是我当年报错的根源。g++在链接的时候,会自动把标准C++库(比如你想用个cout或者STL啥的)给带上。而gcc虽然也能编译C++的源文件,但它在链接的时候很懒,它不会主动去找C++库。所以如果你用gcc编译C++,必须手动在后面挂上参数指明库的位置,否则它就给你闹罢工。

我这些年总结出来的“避坑指南”:

后来我跳槽去了另一家搞嵌入式的公司,带新人的时候,我也总拿这套经验教导他们。在实际干活的时候,咱们没必要非得较劲那个底层逻辑,记住我的实战口诀就行:

写C代码就找gcc,写C++代码直接上g++。别觉得自己是大牛,非要用gcc去手动链接C++库,除了能显得你命令敲得长一点,真没啥实际好处,还容易漏掉参数搞得头大。而且在混合编译的时候,最怕的就是混用这俩玩意儿生成的中间文件。我曾经接过一个前同事留下的烂摊子,里面的Makefile写得乱七八糟,一会儿调用gcc一会儿调用g++,结果链接的时候报了一堆符号找不到的错,我排查了整整两天,发现就是因为符号修饰的规则对不上,气得我差点当场辞职。

再说个大实话。

在现代开发环境里,这俩玩意儿底层用的往往是同一个引擎,只是“外壳”和“默认配置”不同。这就好比是手动挡和自动挡的区别,都能把车开到终点,但你要是明明有自动挡不使,非要去磨合那个离合器,除非你是为了钻研技术,不然在赶进度的时候,真的纯属给自己找不痛快。

我现在在这个研究院里,每天对着几万行的老代码,第一件事就是先把编译脚本里的编译器统一喽。别小看这点区别,真到了大型项目里,这就是稳定性的保障。咱们搞技术的,踏实稳重最重要,别在这些基础工具上翻了船,那才叫晚节不保。