私は大学にいて、プロジェクトのためにCを使用しています。GCCとClangを調査しましたが、ClangはGCCよりもはるかにユーザーフレンドリーです。その結果、Linux上のCおよびC++で開発するために、GCCではなくclangを使用することの利点または欠点は何なのでしょうか?
私の場合、これは本番環境ではなく、学生レベルのプログラムに使用されます。
Clangを使用する場合、GDBでデバッグしてGNU Makeを使用するか、別のデバッガーを使用してユーティリティを作成する必要がありますか?
編集:
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もそれに気づきます 、ファッションの後:
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.
典型的な「Oh my god Clang read my mind」の例ではなく、不明確なエラーメッセージ(文法のあいまいさから生じる)をトリガーする例を意図的に選択します。それでも、Clangはエラーの洪水を回避することに気づきます。生徒を怖がらせる必要はありません。
現在のところ、GCCはClangよりもC++ 11機能をはるかに優れた完全なサポートを提供しています。また、GCCのコードジェネレーターは、Clangのコードジェネレーターよりも優れた最適化を実行します(私の経験では、徹底的なテストを見たことはありません)。
一方、Clangは多くの場合GCCよりも迅速にコードをコンパイルし、コードに何か問題がある場合はより良いエラーメッセージを生成します。
どちらを使用するかの選択は、本当に重要なことに依存します。コンパイルの利便性よりも、C++ 11のサポートとコード生成の品質を重視しています。このため、GCCを使用しています。あなたにとって、トレードオフは異なる可能性があります。
私は両方を使用しますが、それは時々異なる、有用なエラーメッセージを出すからです。
Pythonプロジェクトは、コア開発者の1人が最初にclangでコンパイルしようとしたときに、いくつかの小さなバグレットを見つけて修正することができました。
私はClangとGCCの両方を使用していますが、Clangにはいくつかの有用な警告がありますが、独自のレイトレーシングベンチマークでは、GCCよりも常に一貫して5-15%遅くなっています(もちろん、両方に同様の最適化フラグを使用しようとしました)
そのため、今のところ、Clangの静的分析と複雑なマクロでの警告を使用します(ただし、GCCの警告は、gcc4.8-4.9とほぼ同等です)。
考慮事項:
*****-これらの領域は活発に開発中であり、まもなくサポートされる可能性があります
学生レベルのプログラムの場合、Clangにはデフォルトでより厳密なwrtという利点があります。 C標準。たとえば、次のK&RバージョンのHello WorldはGCCによって警告なしに受け入れられますが、Clangによって拒否され、かなりわかりやすいエラーメッセージが表示されます。
main()
{
puts("Hello, world!");
}
GCCでは、-Werror
を指定して、これが有効なC89プログラムではないことを本当に指摘する必要があります。また、c99
またはgcc -std=c99
を使用してC99言語を取得する必要があります。
Clangは代替手段になると思います。
GCCとclangにはa+++++a
などの式にいくつかの違いがあり、Macでclangを使用しているときにgccを使用している同僚と多くの異なる答えを持っています。
GCCが標準になり、clangが代わりになる可能性があります。 GCCは非常に安定しており、clangはまだ開発中であるためです。