我的 Linux 开发项目的 Clang 与 GCC

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8205858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:23:53  来源:igfitidea点击:

Clang vs GCC for my Linux Development project

c++clinuxgccclang

提问by haziz

I'm in college, and for a project we're using C. We've explored GCC and Clang, and Clang appears to be much more user friendly than GCC. As a result, I'm wondering what the advantages or disadvantages are to using clang, as opposed to GCC, for developing in C and C++ on Linux?

我在上大学,对于一个我们使用 C 的项目。我们探索了 GCC 和 Clang,而 Clang 似乎比 GCC 对用户友好得多。因此,我想知道在 Linux 上使用 C 和 C++ 进行开发时,使用 clang 而非 GCC 有什么优点或缺点?

In my case this would be used for student level programs, not production.

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

If I use Clang, should I debug with GDB and use GNU Make, or use another debugger and make utility?

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

采纳答案by Matthieu M.

EDIT:

编辑:

The gcc guys really improved the diagnosis experience in gcc (ah competition). They created a wiki page to showcase it here. gcc 4.8 now has quite good diagnostics as well (gcc 4.9x added color support). Clang is still in the lead, but the gap is closing.

gcc 的家伙真的提高了 gcc 的诊断体验(啊比赛)。他们创建了维基页面来展示它在这里。gcc 4.8 现在也有很好的诊断功能(gcc 4.9x 添加了颜色支持)。Clang 仍处于领先地位,但差距正在缩小。



Original:

原来的:

For students, I would unconditionally recommend Clang.

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

The performance in terms of generated code between gcc and Clang is now unclear (though I think that gcc 4.7 still has the lead, I haven't seen conclusive benchmarks yet), but for students to learn it does not really matter anyway.

gcc 和 Clang 之间生成代码的性能现在还不清楚(虽然我认为 gcc 4.7 仍然领先,我还没有看到确凿的基准),但对于学生来说,学习它无论如何都无所谓。

On the other hand, Clang's extremely clear diagnostics are definitely easier for beginners to interpret.

另一方面,Clang 极其清晰的诊断对于初学者来说绝对更容易理解。

Consider this simple snippet:

考虑这个简单的片段:

#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";
}

You'll notice right away that the semi-colon is missing after the definition of the Studentclass, right :) ?

您会立即注意到在Student类定义之后缺少分号,对吧:)?

Well, gcc notices it too, after a fashion:

好吧,gcc 也注意到了它,以一种时尚的方式:

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>]

And Clang is not exactly starring here either, but still:

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.

I purposefully choose an example which triggers an unclear error message (coming from an ambiguity in the grammar) rather than the typical "Oh my god Clang read my mind" examples. Still, we notice that Clang avoids the flood of errors. No need to scare students away.

我特意选择了一个触发不明确错误消息的示例(来自语法中的歧义),而不是典型的“哦,我的上帝 Clang 读懂了我的想法”示例。尽管如此,我们注意到 Clang 避免了大量错误。没必要吓跑学生。

回答by Fred Foo

For student level programs, Clang has the benefit that it is, by default, stricter wrt. the C standard. For example, the following K&R version of Hello World is accepted without warning by GCC, but rejected by Clang with some pretty descriptive error messages:

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

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

With GCC, you have to give it -Werrorto get it to really make a point about this not being a valid C89 program. Also, you still need to use c99or gcc -std=c99to get the C99 language.

使用 GCC,您必须提供它-Werror才能真正表明这不是有效的 C89 程序。此外,您仍然需要使用c99gcc -std=c99获取 C99 语言。

回答by Raymond Hettinger

I use both because sometimes they give different, useful error messages.

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

The Python project was able to find and fix a number of small buglets when one of the core developers first tried compiling with clang.

当其中一位核心开发人员第一次尝试使用 clang 进行编译时,Python 项目能够找到并修复一些小的 buglet。

回答by Mankarse

As of right now, GCC has much better and more complete support for C++11 features than Clang. Also, the code generator for GCC performs better optimisation than the one in Clang (in my experience, I have not seen any exhaustive tests).

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

On the other hand, Clang often compiles code more quickly than GCC, and produces better error messages when there is something wrong with your code.

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

The choice of which one to use really depends on what things are important to you. I value C++11 support and code generation quality more than I value convenience of compilation. Because of this, I use GCC. For you, the trade-offs could be different.

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

回答by ideasman42

I use both Clang and GCC, I find Clang has some useful warnings, but for my own ray-tracing benchmarks - its consistently 5-15% slower then GCC (take that with grain of salt of course, but attempted to use similar optimization flags for both).

我同时使用 Clang 和 GCC,我发现 Clang 有一些有用的警告,但对于我自己的光线跟踪基准测试 - 它始终比 GCC 慢 5-15% (当然,这是有道理的,但尝试使用类似的优化标志对彼此而言)。

So for now I use Clang static analysis and its warnings with complex macros: (though now GCC's warnings are pretty much as good - gcc4.8 - 4.9).

所以现在我使用 Clang 静态分析及其带有复杂宏的警告:(尽管现在 GCC 的警告几乎一样好 - gcc4.8 - 4.9)。

Some considerations:

一些考虑:

  • Clang has no OpenMP support, only matters if you take advantage of that but since I do, its a limitation for me. (*****)
  • Cross compilation may not be as well supported (FreeBSD 10 for example still use GCC4.x for ARM), gcc-mingw for example is available on Linux... (YMMV).
  • Some IDE's don't yet support parsing Clangs output (QtCreator for example*****). EDIT: QtCreator now supports Clang's output
  • Some aspects of GCC are better documented and since GCC has been around for longer and is widely used, you might find it easier to get help with warnings / error messages.
  • Clang 没有 OpenMP 支持,只有当你利用它时才重要,但既然我这样做了,它对我来说是一个限制。(*****)
  • 交叉编译可能没有得到很好的支持(例如,FreeBSD 10 仍然使用 GCC4.x for ARM),例如 gcc-mingw 在 Linux 上可用......(YMMV)。
  • 某些 IDE 尚不支持解析 Clangs 输出(例如 QtCreator*****)。编辑:QtCreator 现在支持 Clang 的输出
  • GCC 的某些方面有更好的文档记录,并且由于 GCC 已经存在的时间更长并且被广泛使用,您可能会发现更容易获得警告/错误消息的帮助。

***** - these areas are in active development and may soon be supported

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

回答by songziming

I think clang could be an alternative.

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

GCC and clang have some differences on expressions like a+++++a, and I've got many different answers with my peer who use clang on Mac while I use gcc.

GCC 和 clang 在诸如 之类的表达上存在一些差异a+++++a,我与在 Mac 上使用 clang 而我使用 gcc 的同行有很多不同的答案。

GCC has become the standard, and clang could be an alternative. Because GCC is very stable and clang is still under developing.

GCC 已经成为标准,clang 可能是一个替代方案。因为 GCC 非常稳定,clang 还在开发中。