铿锵VS GCC为我的Linux开发项目

我在上大学,我们正在使用一个项目C.我们已经探索了GCC和Clang,并且Clang似乎比GCC更加用户友好。 因此,我想知道使用clang(而不是GCC)在Linux上用C和C ++进行开发的优缺点是什么?

在我的情况下,这将用于学生级别的程序,而不是生产。

如果我使用Clang,我应该使用GDB进行debugging并使用GNU Make,或者使用另一个debugging器并生成实用程序?

编辑:

海湾合作委员会的人真的提高了海湾合作委员会(ah比赛)的诊断经验。 他们创build了一个wiki页面在这里展示。 gcc 4.8现在有相当好的诊断(gcc 4.9x增加了颜色支持)。 铿锵仍然处于领先地位,但差距正在缩小。


原版的:

对于学生,我会无条件地推荐Clang。

在gcc和Clang之间生成代码的性能目前还不清楚(尽pipe我认为gcc 4.7仍然处于领先地位,但我还没有看到确凿的基准),但是对于学生来说学习它并不重要。

另一方面,Clang的非常明确的诊断对于初学者来说更容易解释。

考虑这个简单的片段:

 #include <string> #include <iostream> struct Student { std::string surname; std::string givenname; } std::ostream& operator<<(std::ostream& out, Student const& s) { return out << "{" << s.surname << ", " << s.givenname << "}"; } int main() { Student me = { "Doe", "John" }; std::cout << me << "\n"; } 

你会立刻注意到在Student类的定义之后分号丢失了吗?

好吧, 海湾合作委员会也注意到 ,时尚之后:

 prog.cpp:9: error: expected initializer before '&' token prog.cpp: In function 'int main()': prog.cpp:15: error: no match for 'operator<<' in 'std::cout << me' /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>] 

而Clang也不是在这里主演,但仍然:

 /tmp/webcompile/_25327_1.cc:9:6: error: redefinition of 'ostream' as different kind of symbol std::ostream& operator<<(std::ostream& out, Student const& s) { ^ In file included from /tmp/webcompile/_25327_1.cc:1: In file included from /usr/include/c++/4.3/string:49: In file included from /usr/include/c++/4.3/bits/localefwd.h:47: /usr/include/c++/4.3/iosfwd:134:33: note: previous definition is here typedef basic_ostream<char> ostream; ///< @isiosfwd ^ /tmp/webcompile/_25327_1.cc:9:13: error: expected ';' after top level declarator std::ostream& operator<<(std::ostream& out, Student const& s) { ^ ; 2 errors generated. 

我故意select一个触发不清楚的错误信息的例子(来自语法中的模糊性),而不是典型的“哦,我的上帝铿锵读我的心”的例子。 不过,我们注意到Clang避免了错误的泛滥。 没有必要吓跑学生。

就目前而言,GCC对C ++ 11function的支持要比Clang更好,更完整。 另外,GCC的代码生成器比Clang的代码生成器有更好的优化(根据我的经验,我没有看到任何详尽的testing)。

另一方面,Clang通常比GCC更快速地编译代码,并且在代码有问题时产生更好的错误消息。

select使用哪一个取决于哪些事情对你很重要。 我重视C ++ 11的支持和代码生成质量,比我重视编译的便利性。 因此,我使用GCC。 对你来说,权衡可能是不同的。

我使用两者,因为他们有时会给出不同的有用的错误消息。

当一个核心开发人员首先尝试使用clang进行编译时,Python项目能够find并修复一些小的bugle。

我同时使用Clang和GCC,我发现Clang有一些有用的警告,但是对于我自己的光线追踪基准 – 它一直比GCC慢5-15% (当然,当然是用盐粒,但是试图使用类似的优化标记对彼此而言)。

所以现在我用Clang静态分析和它的警告与复杂的macros:(虽然现在GCC的警告非常好 – gcc4.8 – 4.9)。

一些考虑:

  • 铿锵没有OpenMP的支持,只有重要的,如果你利用这一点,但因为我这样做,对我来说是一个限制。 (*****)
  • 交叉编译可能不被支持(例如FreeBSD 10仍然使用GCC4.x for ARM),例如gcc-mingw在Linux …(YMMV)上可用。
  • 有些IDE还不支持parsingClangs输出( 例如QtCreator )。 编辑:QtCreator现在支持Clang的输出
  • 海湾合作委员会的某些方面有更好的文件logging,并且由于海湾合作委员会已经存在更长时间并被广泛使用,您可能会发现获得警告/错误消息的帮助更容易。

***** – 这些领域正在积极发展,并可能很快得到支持

对于学生级别的课程,Clang的优势在于,默认情况下是严格的。 C标准。 例如,以下的K&R版本的Hello World被GCC接受而没有任何警告,但被Clang拒绝了,并带有一些很好的描述性的错误信息:

 main() { puts("Hello, world!"); } 

有了GCC,你必须给它 – 很-Werror让它真正地指出这不是一个有效的C89程序。 此外,您仍然需要使用c99gcc -std=c99来获取C99语言。

我认为铿可能是一个select。

GCC和clang在expression式上有一些区别,比如a+++++a ,并且我在使用gcc时在Mac上使用clang的同伴有很多不同的答案。

海湾合作委员会已成为标准,铿锵可以替代。 由于海湾合作委员会非常稳定,铛声仍在发展。