g++和gcc有什么区别?在一般的C++开发中应该使用哪一个?
gcc
和g++
是GNU编译器集合(曾经只是GNU C编译器)的编译器驱动程序。
尽管它们根据文件类型自动确定调用哪些后端(cc1
cc1plus
...),除非使用-x language
进行覆盖,但它们之间存在一些差异。
它们默认值中最重要的区别可能是它们自动链接的库。
根据GCC的在线文档链接选项和g++的调用方式,g++
大致等同于gcc -xc++ -lstdc++ -shared-libgcc
(第一个是编译器选项,后两个是链接器选项)。可以通过同时使用-v
选项运行两者来进行检查(它会显示正在运行的后端工具链命令)。
GCC:GNU编译器集合
gcc
:GNU C编译器
g++
:GNU C++编译器
主要区别:
gcc
编译:*.c\*.cpp
文件分别作为C和C++文件进行编译。g++
编译:*.c\*.cpp
文件,但它们都将被视为C++文件。g++
链接对象文件,则会自动链接std C++库(gcc
不会这样做)。gcc
编译C文件时具有较少的预定义宏。gcc
编译 *.cpp
和 g++
编译*.c\*.cpp
文件时有一些额外的宏。编译 *.cpp
文件时的额外宏:
#define __GXX_WEAK__ 1
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 4
#define __EXCEPTIONS 1
#define __private_extern__ extern
gcc
中使用参数 -lstdc++
可以链接标准的 C++ 库。 - Denilson Sá Maia对于C++,你应该使用g++。
它是同一款编译器(例如GNU编译器集合)。 GCC或G ++只是选择不同的前端和不同的默认选项。
简而言之:如果您使用g ++,前端将告诉链接器您可能想要链接C ++标准库。 GCC前端不会这样做(如果您传递正确的命令行选项,它也可以链接它们)。
man gcc
# GCC(1) GNU
#
# NAME
# gcc - GNU project C and C++ compiler
g++
是GNU编译器集合的C++编译器。就像gnat
是Ada编译器一样,用于gcc
。请参阅使用GNU编译器集合(GCC)
例如,Ubuntu 16.04和18.04中的man g++
命令返回GCC(1)
手册页。
Ubuntu 16.04和18.04中的man gcc
说明...
g++
接受大部分与gcc
相同的选项
并且默认情况下...
gcc
不会添加C++库。 g++
是一个调用GCC并自动指定链接到C++库的程序。它将.c、.h和.i文件视为C++源文件,而不是C源文件,除非使用了-x选项。当预编译具有.h扩展名的C头文件以供C++编译时,此程序也很有用。
在gcc
手册中搜索更多关于gcc
和g++
之间选项差异的详细信息。
一般的C++开发应该使用哪个?
从技术上讲,可以使用gcc
或g++
进行一般的C++开发,并应用相应的选项设置。然而,g++
的默认行为自然与C++开发对齐。
添加了Ubuntu 18.04 'gcc' man page,并且Ubuntu 20.04继续保留以下段落:
运行GCC的常规方式是运行名为
gcc
的可执行文件,或在交叉编译时运行machine-gcc
,或者运行特定版本的GCC时使用machine-gcc-version
。 当编译C++程序时,应该使用g++
来调用GCC。
g++
只是链接到gcc
。因此,g++
的调用可能因工具链而异。
ls -l /Applications/Xcode.app/Contents/Developer/usr/bin
# …
# lrwxr-xr-x 1 root wheel 3 Apr 27 2021 g++ -> gcc
# -rwxr-xr-x 1 root wheel 167120 Nov 23 20:51 gcc
### -- versus --
which -a g++
# /usr/bin/g++
ls -l /usr/bin/g++
# -rwxr-xr-x 1 root wheel 137616 Jan 1 2020 /usr/bin/g++
值得一提的是,如果你将.c
文件传递给gcc编译器,它会将其编译为C语言。
g++的默认行为是将.c
文件视为C++文件(除非指定了-x c
选项)。
尽管 gcc 和 g++ 命令执行的任务非常相似,但是 g++ 被设计成用于编译 C++ 程序;它旨在自动执行正确的操作。
实际上,它们背后使用的是同一个程序。据我了解,两者都会根据文件名扩展名决定将程序编译为 C 还是 C++。这两者都可以链接到 C++ 标准库,但只有 g++ 默认链接。因此,如果你有一个用 C++ 编写的程序,不需要链接到标准库,gcc 也能做到正确编译;但是,g++ 同样可以做到。因此,通常没有理由不使用 g++ 进行一般的 C++ 开发。
我对这个问题产生了兴趣,并进行了一些实验。
我在这里找到了描述,但很简短。
然后我尝试在我的Windows机器上使用gcc.exe和g++.exe进行实验:
$ g++ --version | head -n1
g++.exe (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) 4.6.3
$ gcc --version | head -n1
gcc.exe (gcc-4.6.3 release with patches [build 20121012 by perlmingw.sf.net]) 4.6.3
我尝试编译c89、c99和c++1998的简单测试文件,并且在语言扩展名匹配正确的情况下,这对我来说运行得很好。
gcc -std=c99 test_c99.c
gcc -std=c89 test_c89.c
g++ -std=c++98 test_cpp.cpp
gcc -std=c++98 test_cpp.cpp
但是当我尝试以那种方式运行"Gnu编译器套件"工具时:
$ gcc -std=c++98 test_cpp.c
cc1.exe: warning: command line option '-std=c++98' is valid for C++/ObjC++ but not for C [enabled by default]
但这一个仍然可以无错误地工作
$ gcc -x c++ -std=c++98 test_cpp.c
而且这也是
$ g++ -std=c++0x test_cpp_11.cpp
p.s. 测试文件
$ cat test_c89.c test_c99.c test_cpp.cpp
// C89 compatible file
int main()
{
int x[] = {0, 2};
return sizeof(x);
}
// C99 compatible file
int main()
{
int x[] = {[1]=2};
return sizeof(x);
}
// C++1998,2003 compatible file
class X{};
int main()
{
X x;
return sizeof(x);
}
// C++11
#include <vector>
enum class Color : int{red,green,blue}; // scoped enum
int main()
{
std::vector<int> a {1,2,3}; // bracket initialization
return 0;
}
发现:
如果查看进程树,则似乎gcc和g++是其他工具的后端,而在我的环境中这些工具是:cc1plus.exe、cc1.exe、collect2.exe、as.exe、ld.exe
如果您具有正确的扩展名或设置了正确的-std-x标志,则gcc作为元工具运行良好。请参见此文档
int main(){
int * myptr = new int;
* myptr = 1;
printf("myptr[0] is %i\n",*myptr);
return 0;
}
只有 g++ 能够在我的电脑上成功编译,而 gcc 会报错。
undefined reference to `operator new(unsigned long)'
所以,我的结论是gcc并不完全支持“C++”。看起来,选择g++作为C++源文件的编译器是更好的选择。
gcc和g++都是GNU编译器。它们都可以编译C和C++。不同之处在于对于*.c文件,gcc将其视为C程序,而g++则将其视为C++程序。*.cpp文件被视为C++程序。C++是C的超集,语法更加严格,因此要注意后缀。
g++
还会将.cc
解释为仅限于C++的文件扩展名。 - underscore_d
argv [0]
以确定使用哪个调用。这在核心UNIX实用程序中非常常见。 - user836218g++ 等同于 gcc -xc++ -lstdc++ -shared-libgcc
?文档只说它将 .c、.h 和 .i 视为 C++,并自动链接 libstdc++。如果所发布的命令是正确的,那么一个包含有效 C++ 代码的 .txt 文件应该可以编译,但实际上会返回不支持的文件格式错误。 - s d