Je suis au collège et pour un projet nous utilisons C. Nous avons exploré GCC et Clang, et Clang semble être beaucoup plus convivial que GCC. En conséquence, je me demande quels sont les avantages ou les inconvénients de l’utilisation de clang, par opposition à GCC, pour le développement en C et C++ sous Linux?
Dans mon cas, cela serait utilisé pour les programmes de niveau étudiant, pas pour la production.
Si j'utilise Clang, dois-je déboguer avec GDB et utiliser GNU Make, ou utiliser un autre débogueur et make utility?
EDIT:
Les gars de gcc ont vraiment amélioré l'expérience de diagnostic dans gcc (ah concurrence). Ils ont créé une page wiki pour la présenter ici . gcc 4.8 dispose maintenant d’un bon diagnostic (gcc 4.9x support de couleurs ajouté). Clang est toujours en tête, mais l'écart se réduit.
Original:
Pour les étudiants, je recommanderais sans réserve Clang.
La performance en termes de code généré entre gcc et Clang est maintenant incertaine (bien que je pense que gcc 4.7 reste en tête, je n’ai pas encore vu de points de repère concluants), mais que les étudiants l’apprennent n’importe quand même pas.
D'autre part, les diagnostics extrêmement clairs de Clang sont nettement plus faciles à interpréter pour les débutants.
Considérez cet extrait simple:
#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";
}
Vous remarquerez tout de suite que le point-virgule est manquant après la définition de la classe Student
, n'est-ce pas :)?
Eh bien, gcc le remarque aussi , à la mode:
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>]
Et Clang ne joue pas vraiment ici, mais quand même:
/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.
J'ai choisi à dessein un exemple qui déclenche un message d'erreur peu clair (provenant d'une ambiguïté de la grammaire) plutôt que les exemples typiques "Oh, mon Dieu, lis mon esprit". Néanmoins, nous remarquons que Clang évite le flot d’erreurs. Pas besoin de faire peur aux étudiants.
À l'heure actuelle, GCC prend en charge les fonctionnalités C++ 11 de manière bien meilleure et plus complète que Clang. En outre, le générateur de code pour GCC effectue une optimisation supérieure à celle de Clang (selon mon expérience, je n’ai pas vu de tests exhaustifs).
D'autre part, Clang compile souvent le code plus rapidement que GCC et génère de meilleurs messages d'erreur en cas de problème avec votre code.
Le choix de l’utilisation dépend vraiment de ce qui est important pour vous. J'apprécie davantage le support C++ 11 et la qualité de la génération de code que la commodité de la compilation. Pour cette raison, j'utilise GCC. Pour vous, les compromis pourraient être différents.
J'utilise les deux parce que parfois ils donnent des messages d'erreur différents et utiles.
Le projet Python a été en mesure de trouver et de réparer un certain nombre de petits boutons lorsque l'un des principaux développeurs a essayé de compiler avec clang.
J'utilise à la fois Clang et GCC, je trouve que Clang a quelques avertissements utiles, mais pour mes propres repères de tracé de rayons - il est toujours 5-15% plus lent que GCC (prenez cela avec un grain de sel de bien sûr, mais a essayé d'utiliser des indicateurs d'optimisation similaires pour les deux).
Donc pour l'instant j'utilise l'analyse statique de Clang et ses avertissements avec des macros complexes: (bien que maintenant les avertissements de GCC soient à peu près aussi bons - gcc4.8 - 4.9).
Quelques considérations:
***** - ces domaines sont en développement actif et pourraient bientôt être pris en charge
Pour les programmes de niveau étudiant, Clang présente l'avantage d'être, par défaut, plus strict. le standard C. Par exemple, la version suivante de Hello World K & R est acceptée sans avertissement par GCC, mais rejetée par Clang avec quelques jolis messages d'erreur descriptifs:
main()
{
puts("Hello, world!");
}
Avec GCC, vous devez lui donner -Werror
pour le faire comprendre que ce n’est pas un programme C89 valide. De plus, vous devez toujours utiliser c99
ou gcc -std=c99
pour obtenir le langage C99.
Je pense que Clang pourrait être une alternative.
GCC et clang ont des différences sur des expressions comme a+++++a
, et j'ai beaucoup de réponses différentes avec mon pair qui utilise clang sur Mac alors que j'utilise gcc.
GCC est devenu la norme, et Clang pourrait être une alternative. Parce que GCC est très stable et que le son est encore en développement.