我正在上大学,并且对于一个正在使用C的项目,我们已经探索了GCC和Clang,并且Clang似乎比GCC更友好。结果,我想知道使用clang(相对于GCC)在Linux上用C和C ++进行开发有什么优点或缺点?
就我而言,这将用于学生级别的课程,而不是生产课程。
如果使用Clang,应该使用GDB调试并使用GNU Make,还是使用其他调试器和make实用程序?
编辑:
海湾合作委员会的成员确实改善了海湾合作委员会(啊竞争)的诊断经验。他们创建了一个Wiki页面在此处进行展示。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类之后,分号就消失了,对:)吗?
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.
我故意选择一个示例,该示例会触发一个不清楚的错误消息(来自语法上的歧义),而不是典型的“哦,我的上帝Clang读了我的思想”示例。尽管如此,我们注意到Clang避免了大量错误。无需将学生吓跑。