Clang vs GCC用于我的Linux开发项目

时间:2011-11-21 00:01:52

标签: c++ c linux gcc clang

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

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

如果我使用Clang,我应该使用GDB调试并使用GNU Make,还是使用其他调试器并使用实用程序?

6 个答案:

答案 0 :(得分:110)

修改

gcc家伙真的改善了gcc的诊断经验(比赛啊)。他们创建了一个wiki页面来展示它here。 gcc 4.8现在也具有相当好的诊断功能(gcc 4.9x增加了颜色支持)。 Clang仍处于领先地位,但差距正在缩小。


<强>原始

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

gcc和Clang之间生成代码的表现现在还不清楚(虽然我认为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类的定义之后缺少分号,对吧?

嗯,gcc notices it too,时尚之后:

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.

我故意选择一个触发不明确错误信息的例子(来自语法中的含糊不清),而不是典型的“噢,我的上帝Clang读了我的思绪”的例子。尽管如此,我们还是注意到Clang避免了大量的错误。不需要吓跑学生。

答案 1 :(得分:34)

截至目前,GCC对C ++ 11功能的支持比Clang更好,更完整。此外,GCC的代码生成器执行比Clang更好的优化(根据我的经验,我没有看到任何详尽的测试)。

另一方面,Clang经常比GCC更快地编译代码,并在代码出错时产生更好的错误消息。

选择使用哪一个真正取决于对您来说重要的事情。我重视C ++ 11支持和代码生成质量,而不是重视编译的便利性。因此,我使用GCC。对你而言,权衡可能会有所不同。

答案 2 :(得分:23)

我同时使用它们,因为有时它们会提供不同的,有用的错误消息。

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

答案 3 :(得分:10)

我同时使用Clang和GCC,我发现Clang有一些有用的警告,但是对于我自己的光线跟踪基准 - 它一直比GCC 慢5-15%(当然,那就是盐,但是试图对两者使用类似的优化标志。

所以现在我使用Clang静态分析及其对复杂宏的警告:(虽然现在GCC的警告非常好 - gcc4.8 - 4.9)。

一些注意事项:

  • Clang没有OpenMP支持,只有你利用它才有意义,但是因为我这样做,这对我来说是一个限制。 (*****)
  • 交叉编译可能不太受支持(例如FreeBSD 10仍然使用GCC4.x for ARM),例如gcc-mingw在Linux上可用...(YMMV)。
  • 某些IDE还不支持解析Clangs输出( QtCreator例如 *****)。 编辑:QtCreator现在支持Clang的输出
  • GCC的某些方面有更好的文档记录,而且由于GCC已存在更长时间且被广泛使用,您可能会发现更容易获得有关警告/错误消息的帮助。

***** - 这些领域正在积极开发中,可能很快就会得到支持

答案 4 :(得分:7)

对于学生级别的课程,Clang的优点是默认情况下更严格。 C标准。例如,以下K&amp; R版本的Hello World在没有GCC警告的情况下被接受,但被Clang拒绝了一些非常具有描述性的错误消息:

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

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

答案 5 :(得分:3)

我认为clang可能是另一种选择。

GCC和clang在像a+++++a这样的表达方面有一些差异,我和我的同伴在使用gcc时在Mac上使用clang有很多不同的答案。

海湾合作委员会已成为标准,而铿锵可能是另一种选择。因为海湾合作委员会非常稳定,而且仍处于发展阶段。