C est l’une des langues les plus utilisées au monde. Il représente une énorme proportion du code existant et continue à être utilisé pour une grande quantité de nouveau code. Il est tellement apprécié par ses utilisateurs, il est tellement répandu que pouvoir exécuter C est pour beaucoup la définition informelle d’une plate-forme , et ses fans le félicitent d’être un "petit" langage avec un ensemble de fonctionnalités relativement propres.
Alors où sont tous les compilateurs?
Sur le bureau, il y en a (de manière réaliste) deux : GCC et Clang. En y réfléchissant quelques secondes, vous vous souviendrez probablement qu'Intel existe également. Il y en a une poignée d'autres, beaucoup trop obscurs pour qu'une personne moyenne puisse les nommer et ne voulant presque pas supporter une version linguistique récente (ou souvent même un sous-ensemble linguistique bien défini, juste un "sous-ensemble"). La moitié des membres de cette liste sont des notes de bas de page historiques; la plupart des autres sont très spécialisés et n'implémentent toujours pas le langage complet. Très peu semblent réellement être open-source.
Scheme et Forth - d’autres petites langues aimées par leurs fans - ont probablement plus de compilateurs que d’utilisateurs réels. Même quelque chose comme SML a plus d'implémentations «sérieuses» à choisir que C. Alors que l'annonce d' un nouveau compilateur C (inachevé) visant à la vérification entraîne des réactions plutôt négatives, et que les implémentations anciennes ont du mal à obtenir suffisamment de contributeurs pour même rattraper C99.
Pourquoi? L'application de C est-elle si difficile? Ce n'est pas C ++. Les utilisateurs ont-ils simplement une idée très biaisée du groupe de complexité auquel il appartient (c.-à-d. Qu'il est plus proche de C ++ que de Scheme)?
Réponses:
Aujourd'hui, vous avez besoin d' un compilateur C réel pour être un compilateur d'optimisation , notamment parce que C n'est plus une langue proche du matériel, car actuels processeurs sont complexes incroyablement ( hors-ordre , pipelinée , superscalaire , avec complexes caches et TLB , donc besoin d’ ordonnancement des instructions , etc ...). Les processeurs x86 actuels ne ressemblent pas aux processeurs i386 du siècle précédent, même s'ils sont capables d'exécuter le même code machine. Voir que le C n'est pas un langage de bas niveau (votre ordinateur n'est pas un PDP-11 rapide), article de David Chisnall.
Peu de gens utilisent des compilateurs C naïfs, non optimiseurs, tels que tinycc ou nwcc , car ils produisent un code plusieurs fois plus lent que ce que les compilateurs optimiseurs peuvent générer.
Coder un compilateur d'optimisation est difficile. Notez que GCC et Clang optimisent tous deux la représentation de code "neutre par rapport au langage source" (Gimple pour GCC, LLVM pour Clang). La complexité d'un bon compilateur C n'est pas en phase d'analyse!
En particulier, créer un compilateur C ++ n’est pas beaucoup plus difficile que de faire un compilateur C: analyser C ++ et le transformer en représentation de code interne est complexe (car la spécification C ++ est complexe), mais il est bien compris, mais les éléments d’optimisation sont encore plus complexes. complexe (à l’intérieur de GCC: les optimisations moyennes, neutres en langage source et en processeur cible, constituent le composant principal du compilateur, le reste étant équilibré entre des interfaces pour plusieurs langues et des interfaces pour plusieurs processeurs). Par conséquent, la plupart des compilateurs C optimiseurs sont également capables de compiler d'autres langages, tels que C ++, Fortran, D, ... Les parties spécifiques à C ++ de GCC représentent environ 20% du compilateur ...
De plus, C (ou C ++) est si largement utilisé que les utilisateurs s'attendent à ce que leur code soit compilable même s'il ne suit pas exactement les normes officielles, qui ne définissent pas assez précisément la sémantique du langage (chaque compilateur peut donc avoir sa propre interprétation). de celui-ci). Regardez aussi dans le compilateur C prouvé CompCert , et l' analyseur statique Frama-C , qui se soucient de la sémantique plus formelle de C.
Et les optimisations sont un phénomène de longue haleine : il est facile d'implémenter quelques optimisations simples, mais elles ne rendront pas un compilateur compétitif! Vous devez implémenter de nombreuses optimisations, et les organiser et les combiner intelligemment, pour obtenir un compilateur réel compétitif. En d'autres termes, un compilateur d'optimisation réel doit être un logiciel complexe. BTW, GCC et Clang / LLVM disposent de plusieurs générateurs de code C / C ++ spécialisés internes. Et les deux sont de grosses bêtes (plusieurs millions de lignes de code source, avec un taux de croissance de plusieurs pour cent par an) avec une importante communauté de développeurs (quelques centaines de personnes travaillant principalement à temps plein ou au moins à mi-temps).
Notez qu’il n’existe pas (à ma connaissance) de compilateur C multithreads, même si certaines parties d’un compilateur pourraient être exécutées en parallèle (par exemple, optimisation intra-procédurale, allocation de registre, ordonnancement des instructions, etc.). Et construire en parallèle avec
make -j
n'est pas toujours suffisant (surtout avec LTO ).En outre, il est difficile d’obtenir des fonds pour coder un compilateur C à partir de rien, et cet effort doit durer plusieurs années. Enfin, la plupart des compilateurs C ou C ++ sont aujourd'hui des logiciels libres (il n'y a plus de marché pour les nouveaux compilateurs propriétaires vendus par les startups) ou du moins sont des produits monopolistiques (comme Microsoft Visual C ++ ), et être un logiciel libre est presque indispensable pour les compilateurs ( car ils ont besoin des contributions de nombreuses organisations différentes).
Je serais ravi d'obtenir des fonds pour travailler sur un compilateur C à partir de rien en tant que logiciel libre, mais je ne suis pas assez naïf pour croire que c'est possible aujourd'hui!
la source
(there is no more a market for proprietary compilers
Dites-le à l'équipe de Visual Studio ...J'aimerais contester votre hypothèse sous-jacente selon laquelle il n'y a qu'un petit nombre d'implémentations en C.
Je ne connais même pas C, je n'utilise pas C, je ne suis pas membre de la communauté C et pourtant, même si j'en connais beaucoup plus que les quelques compilateurs que vous avez mentionnés.
D'abord et avant tout, il y a le compilateur qui gomme probablement complètement GCC et Clang sur le bureau: Microsoft Visual C. En dépit des avancées faites par OSX et Linux sur le bureau, et la part de marché qu'iOS et Android ont "volée" loin des anciens utilisateurs de bureau traditionnels, Windows est toujours le système d'exploitation dominant et la majorité des programmes C de bureau Windows sont probablement compilés à l'aide d'outils Microsoft.
Traditionnellement, chaque fournisseur de système d'exploitation et chaque fournisseur de puces disposaient de leurs propres compilateurs. Microsoft, en tant que fournisseur de système d’exploitation, dispose de Microsoft Visual C. IBM, en tant que fournisseur de système d’exploitation et fournisseur de puces, comporte XLC (qui est le compilateur système par défaut pour AIX et le compilateur avec lequel AIX et i / OS sont compilés) . Intel a son propre compilateur. Sun / Oracle ont leur propre compilateur dans Sun Studio.
Viennent ensuite les éditeurs de compilateurs hautes performances tels que PathScale et The Portland Group, dont les compilateurs (et les bibliothèques OpenMP) sont utilisés pour la numérotation.
Digital Mars est également toujours en activité. Je crois que Walter Bright a la particularité d'être la seule personne sur la planète à avoir réussi à créer lui-même un compilateur C ++ de qualité production.
Enfin, nous avons tous les compilateurs exclusifs pour les microcontrôleurs intégrés. IIRC, le nombre de microcontrôleurs vendus chaque année est supérieur à celui des processeurs de bureau, mobiles, serveurs, stations de travail et ordinateurs centraux, vendus depuis le début de l’histoire de l’informatique combinée. Donc, ce ne sont certainement pas des produits de niche.
Une mention honorifique revient à TruffleC , un interprète C (!) Fonctionnant sur la JVM (!) Écrit à l’aide du framework d’interpréteur Truffle AST qui est seulement 7% plus lent que GCC et Clang (celui qui est le plus rapide sur un repère donné) sur le Jeu de benchmark de langues informatiques, et plus rapide que les deux sur les microbenchmarks. En utilisant TruffleC, l'équipe de Truffle a pu obtenir que sa version de JRuby + Truffle exécute des extensions Ruby C plus rapidement que l'implémentation réelle de C Ruby!
Donc, ce sont 6 implémentations en plus de celles que vous avez énumérées et que je peux nommer à mon insu, sans même rien savoir de C.
la source
De combien de compilateurs avez-vous besoin?
S'ils ont des ensembles de fonctionnalités différents, vous créez un problème de portabilité. Si elles sont banalisées, vous choisissez soit le "défaut" (GCC, Clang ou VS). Si vous vous souciez des 5% restants, vous avez un point de repère.
Si vous travaillez en langage de programmation de manière récréative ou à des fins de recherche, vous utiliserez probablement une langue plus moderne. D'où la multiplication des compilateurs de jouets pour Scheme et ML. Bien que OCaml semble gagner du terrain pour des utilisations non académiques non jouets.
Notez que cela varie beaucoup selon la langue. Java a essentiellement les outils Sun / Oracle et GNU. Python a divers compilateurs dont aucun n’est vraiment respecté par rapport à l’interprète standard. Rust et Go ont exactement une implémentation chacun. C # a Microsoft et Mono.
la source
1000 * 0
c'est toujours0
.int
, et obligera différents compilateurs à interpréter le même code source de manière très différente.6g
/8g
/… et gccgo). Il existait également une implémentation commerciale propriétaire très intéressante appelée erGo, qui était a) une implémentation Windows native de Go à un moment où ni gccgo ni le compilateur Go d'origine ne fonctionnaient très bien sous Windows, b) une entreprise pariant sur Go, longue avant même de devenir 1.0, et c) la première mise en œuvre de Go écrite en Go (gccgo et 6g / 8g sont tous deux écrits en C). Le projet et la société ont toutefois disparu avant même de sortir de la bêta fermée.C / C ++ est unique parmi les langages compilés en ce qu'il a 3 implémentations majeures d'une spécification commune.
Selon la règle de rejeter tout ce qui est peu utilisé, tout autre langage compilé a un score de 0 à 1.
Et je pense que javascript est la seule raison pour laquelle vous devez spécifier «compilé».
la source
uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;
comme affectantb
la valeur 8192. Certains le définissent comme affectant 1152000000. La plupart du temps le considère comme un comportement indéfini et susceptible de stocker 3299483648 mais ne fait aucune promesse à cet égard.2
ou2u
apparemment./2u
? Le débordement non signé est défini (en tant que modulo 2 ^ N pour le N défini par la mise en oeuvre), mais la division ne peut même pas déborder.int
, mais dont le produit ne rentrerait pas dans ce type. Le fait de forcer ce résultat vers un entier non signé signifierait probablement que l'interprétation de la valeur résultante serait modifiée, mais n'annulerait pas le comportement non défini du calcul précédent.Alors, quelle est votre langue cible?
Les compilateurs SML ciblent souvent C ou quelque chose comme LLVM (ou comme vous le voyez dans votre lien, la JVM ou JavaScript).
Si vous compilez C, ce n'est pas parce que vous allez sur la JVM. Vous allez à quelque chose de pire que C. Bien pire. Et ensuite, vous pouvez dupliquer cet enfer mineur un tas de fois pour toutes vos plates-formes cibles.
Et bien sûr, C n'est pas C ++, mais je dirais que c'est plus proche de C ++ que de Scheme. Il a son propre sous-ensemble de pervers comportements indéfinis (je regarde votre taille de types intégrés). Et si vous bousillez ces minuties (ou si vous le faites "correctement" mais de manière inattendue), vous disposez alors de décennies de code existant sur des systèmes vitaux qui vous diront à quel point vous êtes terrible. Si vous bousillez un compilateur SML, cela ne fonctionnera tout simplement pas - et quelqu'un pourrait s'en rendre compte. Un jour.
la source
int
à avoir 32 ou 64 bits, mais cela peut être aussi petit que 16 bits. Ce n'est pas difficile du tout de produire un nombre en dehors de la plage[−32767, +32767]
et leint
débordement est UB. Il y a aussichar
/short
se promuint
ouunsigned int
selon queint
peut représenter chaque valeur du type d' origine, ce qui peut encore déclencher une conversion à partirint
deunsigned int
si les opérandes avaient différents types et se sont convertis différemment, plus potentiellement une autre conversion lorsque vous attribuez le résultat à une variable .