LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2509|回复: 23

“gcc和g++的区别”以及“gcc工作流程”问题请教

[复制链接]
发表于 2009-5-16 13:55:59 | 显示全部楼层 |阅读模式
误区一:gcc只能编译c代码,g++只能编译c++代码

两者都可以,但是请注意:
1.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的,例如:
#include <stdio.h>
int main(int argc, char* argv[]) {
   if(argv == 0) return;
   printString(argv);
   return;
}
int printString(char* string) {
  sprintf(string, "This is a test.\n");
}

如果按照C的语法规则,OK,没问题,但是,一旦把后缀改为cpp,立刻报三个错:“printString未定义”;
“cannot convert `char**' to `char*”;
”return-statement with no value“;
分别对应前面红色标注的部分。可见C++的语法规则更加严谨一些。
2.编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。

误区二:gcc不会定义__cplusplus宏,而g++会

实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。

误区三:编译只能用gcc,链接只能用g++
严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。

这个是网上盛传的一份文档,有些地方很困惑,还请大侠来解惑~~
对于误区一:
gcc和g++是否只根据文件的后缀名来决定文件的是c还是c++?
对于gcc,只有.c才是c程序,其他的诸如C cpp cxx都是c++程序?
而对于g++,上面提到的都是c++?

对于误区三:
不管gcc还是g++,他们都是通过调用其他的程序来完成编译、连接工作的。特别的是这里提到的链接,这个不是ld的工作么?怎么说是g++或者gcc -lstdc++来完成的呢?
还有g++在链接时会调用gcc,又是怎么回事呢?gcc和g++编译时都是通过调用cc1或者cc1plus来完成的,这里g++在编译阶段会自动调用gcc做何理解呢?
发表于 2009-5-16 16:04:41 | 显示全部楼层
请 给出 引用 来源。
写这种混淆视听文章的家伙该打屁屁!:hanged:

扫盲:
GCC 早期意思是 GNU C Compiler,专指 GNU 的 C语言 编译器;
随着其发展加入常见计算机语言支持,意思变为现在的 GNU Compiler Collection。


如果您自己不是太明白,那请按习惯做:gcc 编译 c 程序,g++ 编译 c++ 程序。

如果想利用一下 c++ 强大的检查能力,那可以使用 g++ 来编译 c 程序。
这样做,骨子里是“把 c++ 当作 更好的 c 来看待”,属于恶习。
正确的做法是,养成良好的编程习惯,而不应依赖编译器来查错。

用 gcc 直接编译 c++ 同样属于恶习。

您可以把“连接”看成编译过程的一部分,也可以把编译过程看作若干个独立步骤,视您具体目的而定。
一般的编译过程不需要您考虑这些。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 18:00:33 | 显示全部楼层
http://www.google.cn/search?hl=z ... a=&aq=f&oq=
这个网上很多的,只是不知道是谁第一个写出来的

深空老大,您说的很有道理,但是有些地方,我很想知道为什么是那样的,所以就会有些很奇怪的问题
gcc编译c++时需要加上-lstdc++选项
g++编译c源码时,是把它作为c程序来处理还是c++程序来处理的呢?链接时是使用libstdc还是libstdc++呢?

在GCC:The Complete Reference中看到:
A version of gcc that sets the default language to C++ and automatically includes the standard C++ libraries when linking. This is the same as g++.

我想知道gcc跟g++的异同点在哪里?仅仅是编译时调用cc1plus、然后连接时用的是libstdc++?然后其他的地方都一样?
在code::block中的设置中有看到:
[color="Red"]Linker for dynamic libs:g++.exe
linker for static libs:ar
这个又是什么意思呢?linker的工作不是都是由ld来完成的么?怎么会涉及到g++和ar呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 18:02:11 | 显示全部楼层
您可以把“连接”看成编译过程的一部分,也可以把编译过程看作若干个独立步骤,视您具体目的而定。

这样说的好像是一个意思
我一直都是把链接看做编译过程的一部分,因为我觉得编译的最终结果是得到可执行的二进制文件,所以肯定包含linker这一步工作
回复 支持 反对

使用道具 举报

发表于 2009-5-16 19:41:11 | 显示全部楼层
偶上一帖已针对您个人的情况(适用于大部分人,包括偶自己)做了合理解答:“[color="Red"]您不需要考虑这些”。

如果真的感兴趣、或者精力过剩,那您可以找本 编译原理 方面的书补补,这些东西解释清楚本就是一本书。
如果这样还是不能满足,那您可以打开 gcc 的源代码好好读读(不妨从代码量小的早期 gcc 版本开始)、或建立一个简单的计算机语言程序(不妨从写计算器开始)。


您需要明白的是,习惯上什么是正确的,习惯上什么是错误的,而不是您认为什么怎么样。
下面是您需要知道的:
/usr/bin/cpp 是 gnu 的 c语言 预处理器,
/usr/bin/gcc 是 gnu 的 c语言 编译器,
/usr/bin/g++ 是 gnu 的 c++语言 编译器,/usr/lib/libstdc++.* 是 gnu 的 c++语言 支持的一部分,
c++语言 是 c语言 的 超集,c++语言 完全兼容 c语言,(如果不满意这个解释,您可以找找 c++、c 标准看看)
/usr/bin/as 是 gnu 的 汇编器,
/usr/bin/ld 是 gnu 的 链接器,
我们习惯上说的 编译(习惯用法) 实际是由 预处理、编译(这个才是其本意)、汇编、链接 这些步骤组成,默认 gcc g++ 会自动为您完成整个 编译链接 过程。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 20:35:42 | 显示全部楼层
我想对这些了解一点,不满足于习惯的做法,但是这样也不一定意味着我要成为专业的人士。所以才会有这些问题。
譬如这些:
gcc并不能说是gnu的c编译器,他只是个front-end,具体的编译工作是cc1来完成的
gcc并不是直接调用ld的,是通过collect2来的,但是这个过程又是怎样的?collect2是通过什么方法来找到合适的ld的?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 20:48:05 | 显示全部楼层
GCC uses a utility called collect2 on nearly all systems to arrange to call various initialization functions at start time.

The program collect2 works by [color="Red"]linking the program once and looking through the linker output file for symbols with particular names indicating they are constructor functions. If it finds any, it creates a new temporary `.c' file containing a table of them, compiles it, and [color="Red"]links the program a second time including that file.
这里需要做两回链接,这两次都是通过调用ld来的么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 20:48:52 | 显示全部楼层
The actual calls to the constructors are carried out by a subroutine called __main, which is called (automatically) at the beginning of the body of main (provided main was compiled with GNU CC). Calling __main is necessary, even when compiling C code, to allow linking C and C++ object code together. (If you use -nostdlib, you get an unresolved reference to __main, [color="Red"]since it's defined in the standard GCC library. Include -lgcc at the end of your compiler command line to resolve this reference.)
这个__main跟main()有什么分别得呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-16 20:51:21 | 显示全部楼层
The program collect2 is installed as ld in the directory where the passes of the compiler are installed. When collect2 needs to find the real ld, it tries the following file names:
    * a hard coded linker file name, if GCC was configured with the --with-ld option.
[color="Red"]    * real-ld in the directories listed in the compiler's search directories.
    * real-ld in the directories listed in the environment variable PATH.
    * The file specified in the REAL_LD_FILE_NAME configuration macro, if specified.
[color="Red"]    * ld in the compiler's search directories, except that collect2 will not execute itself recursively.
    * ld in PATH.
第二个选项跟第五个选项有什么分别得呢?感觉一样的啊!
第三个选项跟第六个选项有什么分别得呢?
回复 支持 反对

使用道具 举报

发表于 2009-5-16 21:38:03 | 显示全部楼层
偶前两贴给出的解释已经从适合大多数人的角度解释了您标题的问题。

您现在不停发的贴讨论的问题范围已经明显超出标题范围。
整个论坛上对这些问题清清楚楚的人估计不超过 10 个,偶大概能算半个的半个,您已经比偶强多了。
所以[color="Red"]解决您现在疑问的最好办法,还是读 gcc 源码
,把 gcc binutils 官网文档过一遍先 是个不错的主意。


作为习惯的一部分,请注意 libexec 对应目录下的程序 一般 不是给用户直接使用的,而是由其他程序调用简洁执行,比如您提到的 cc1 等 是由 gcc 调用执行。

/usr/bin/gcc 本身确实是前端,但不应按您想当然的方式理解。
如果愿意,您可以把其当作模块化编程的一个范例。
要知道 gcc 现在几乎无处不在,并且正在被移植到 更多的OS、更多的硬件平台。

您真正应该考虑的 是 为什么存在这些习惯(传统)?为什么要这样做?

另,请 给出 引用 出处,断章取义会害死人的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表