Pourquoi les gens utilisent-ils le C s'il est si dangereux?


132

J'envisage d'apprendre C.

Mais pourquoi les gens utilisent-ils C (ou C ++) s’il peut être utilisé «dangereusement»?

Par dangereux, je veux dire avec des pointeurs et autres choses similaires.

J'aime la question Stack Overflow Pourquoi la fonction gets est-elle si dangereuse qu'elle ne devrait pas être utilisée? . Pourquoi les programmeurs n'utilisent-ils pas simplement Java ou Python ou un autre langage compilé tel que Visual Basic?


152
Pourquoi les chefs utilisent-ils des couteaux s'ils peuvent être utilisés «dangereusement»?
Oerkelens

78
Un grand pouvoir implique de grandes responsabilités.
Pieter B

10
Joe Blow, pontificat beaucoup?
Matthew James Briggs

4
Parce que "Back In The Day", lorsque C est devenu la langue de choix, nous nous attendions à ce que nous puissions gérer ce genre de choses, car nous le devions. Les langues interprétées ou codées en octets étaient trop lentes car les processeurs du jour étaient beaucoup plus lents. (Aujourd'hui, je peux acheter un ordinateur de bureau bas de gamme doté d'un processeur multicœur de 2+ GHz et de 4 Go de mémoire de Dell pour 279 $. Vous ne savez pas à quel point cela semble incroyable à un type comme moi pour qui un ordinateur 4 MHz avec 640 kilo - octets de mémoire était le bonheur ...). La loi de Moore a gagné. Jeu. Plus de!
Bob Jarvis

6
@Bob Jarvis: Le jeu n'est pas terminé. Si vous pensez que votre PC à 2 + GHz, 4 Go - ou même votre cluster de plusieurs centaines de PC à 4 GHz avec les derniers GPU CUDA, ou autre - est assez rapide, vous ne travaillez tout simplement pas assez fort :-)
jamesqf

Réponses:


246
  1. C précède de nombreuses autres langues auxquelles vous songez. Une grande partie de ce que nous savons maintenant sur la façon de rendre la programmation "plus sûre" provient de l’expérience de langages comme le C.

  2. La plupart des langues plus sûres apparues depuis C utilisent un runtime plus long, un jeu de fonctionnalités plus complexe et / ou une machine virtuelle pour atteindre leurs objectifs. En conséquence, le C est resté quelque chose d'un "plus petit commun dénominateur" parmi toutes les langues populaires / grand public.

    • C est un langage beaucoup plus facile à mettre en œuvre car il est relativement petit et plus susceptible de fonctionner correctement, même dans les environnements les plus faibles. Ainsi, de nombreux systèmes embarqués qui ont besoin de développer leurs propres compilateurs et autres outils sont plus susceptibles de fournir un compilateur fonctionnel. pour C.

    • Comme le C est si petit et si simple, les autres langages de programmation ont tendance à communiquer entre eux via une API de type C. C’est probablement la raison principale pour laquelle C ne mourra jamais vraiment, même si la plupart d’entre nous n’interagissent jamais avec lui que par le biais de wrappers.

  3. La plupart des langages "plus sûrs" qui tentent d'améliorer C et C ++ n'essayent pas d'être des "langages systèmes" qui vous donnent un contrôle presque total sur l'utilisation de la mémoire et le comportement à l'exécution de votre programme. Même s’il est vrai que de plus en plus d’applications de nos jours n’ont tout simplement pas besoin de ce niveau de contrôle, il y aura toujours quelques cas où cela sera nécessaire (en particulier dans les machines virtuelles et les navigateurs qui implémentent tous ces langages sûrs et sûrs pour le Web). reste de nous).

    Aujourd'hui, il existe quelques langages de programmation système (Rust, Nim, D, ...) qui sont plus sûrs que C ou C ++. Ils ont les avantages du recul et se rendent compte que la plupart du temps, un tel contrôle fin n’est pas nécessaire; offrez donc une interface généralement sécurisée avec quelques modes / crochets dangereux sur lesquels vous pouvez passer lorsque cela est vraiment nécessaire.

  4. Même en C, nous avons appris beaucoup de règles et de directives qui tendent à réduire considérablement le nombre de bugs insidieux apparus dans la pratique. Il est généralement impossible d’obtenir la norme pour appliquer ces règles de manière rétroactive, car cela endommagerait trop de code existant, mais il est courant d’utiliser des avertissements du compilateur, des linters et d’autres outils d’analyse statique pour détecter ce type de problèmes facilement évitables. Le sous-ensemble de programmes C qui utilisent ces outils avec brio est déjà bien plus sûr que "juste C", et tout programmeur C compétent en utilisera quelques-uns aujourd'hui.


En outre, vous ne ferez jamais un concours Java obscurci aussi divertissant que le concours C obscurci .


7
"plus petit dénominateur commun" semble dénigrant. Je dirais que, contrairement aux nombreux langages beaucoup plus lourds, C n'applique pas une tonne de bagages supplémentaires dont vous n'avez pas besoin et vous fournit une base ultra-rapide sur laquelle mettre en œuvre les éléments dont vous avez besoin. Est-ce ce que vous vouliez dire?
underscore_d

9
"Vous ne pouvez pas vraiment avoir l'un sans l'autre.": En fait, beaucoup de nouvelles langues (Rust, Nim, D, ...) tentent de le faire. Cela revient essentiellement à faire correspondre un sous-ensemble "sûr" du langage avec deux primitives "non sûres" lorsque ce niveau de contrôle est absolument nécessaire. Cependant, tous ces éléments s’appuient sur les connaissances acquises en C et C ++, c’est pourquoi il faudrait peut-être dire qu’à l’époque, les langages C et C ++ ont été développés. leurs bits "dangereux", mais ils ne ont pas encore rattrapé.
Matthieu M.

6
1) n'est pas un point valide! C a emprunté des traits à Algol 68, qui est un langage "sûr" en ce sens; de sorte que les auteurs connaissaient de telles langues. Les autres points sont super.
Reinierpost

4
@MatthieuM. Vous voudrez peut-être aussi consulter Microsoft Research. Ils ont produit quelques systèmes d’exploitation gérés au cours des deux ou trois dernières décennies, dont certains sont plus rapides (tout à fait accidentellement - l’objectif principal de la plupart de ces systèmes de recherche est la sécurité et non la vitesse) par rapport à un système d’exploitation équivalent non géré pour certaines charges de travail réelles. . L’accélération est principalement due aux contraintes de sécurité: les vérifications d’exécutables statiques et dynamiques permettent des optimisations non disponibles dans du code non géré. Il y a pas mal de
choses

3
@Luaan: Midori a l'air si génial; Je suis toujours impatient de lire les articles du blog de Joe.
Matthieu M.

41

Premièrement, C est un langage de programmation système. Ainsi, par exemple, si vous écrivez une machine virtuelle Java ou un interpréteur Python, vous aurez besoin d'un langage de programmation système pour les écrire.

Deuxièmement, C fournit des performances que les langages tels que Java et Python ne fournissent pas. En règle générale, l'informatique haute performance sous Java et Python utilise des bibliothèques écrites dans un langage haute performance tel que C pour faire le gros du travail.

Troisièmement, l’empreinte C est beaucoup plus petite que des langages tels que Java et Python. Cela le rend utilisable pour les systèmes intégrés, qui peuvent ne pas disposer des ressources nécessaires pour prendre en charge les grands environnements d'exécution et les demandes de mémoire de langages tels que Java et Python.


Un "langage de programmation système" est un langage approprié pour construire des systèmes de niveau industriel avec; en l'état, Java et Python ne sont pas des langages de programmation système. "Ce qui fait exactement un langage de programmation système" n'entre pas dans le cadre de cette question, mais un langage de programmation système doit prendre en charge l'utilisation de la plate-forme sous-jacente.

D'autre part (en réponse aux commentaires), un langage de programmation système n'a pas besoin d'être auto-hébergé. Cette question a été soulevée parce que la question initiale posée : « Pourquoi les gens utilisent C », le premier commentaire demandé « pourquoi auriez - vous besoin d' un langage comme C » lorsque vous avez PyPy, et je note que PyPy ne en fait utiliser C. Ainsi, il était à l’origine pertinente pour la question, mais malheureusement (et source de confusion) "auto-hébergement" n’est pas réellement pertinente pour cette réponse. Je suis désolé d'avoir soulevé la question.

Donc, pour résumer: Java et Python ne conviennent pas à la programmation système, non pas parce que leurs implémentations principales sont interprétées, ou parce que les implémentations compilées nativement ne sont pas auto-hébergées, mais parce qu'elles ne fournissent pas le support nécessaire pour travailler avec la plate-forme sous-jacente.


19
"Si vous écrivez une machine virtuelle Java ou un interpréteur Python, vous aurez besoin d'un langage de programmation système pour les écrire." Euh Comment expliquez-vous PyPy? Pourquoi auriez-vous besoin d'un langage comme C pour écrire un compilateur, un interprète ou une machine virtuelle?
Vincent Savard

10
Je pense que vous avez affirmé avoir besoin d’un langage de programmation système pour écrire une machine virtuelle Java ou un interpréteur Python lorsque vous avez déclaré que "si vous écrivez une machine virtuelle Java ou un interpréteur Python, vous aurez besoin d’un langage de programmation système pour les écrire". Si PyPy ne vous satisfait pas, vous pouvez également rechercher tout interpréteur ou compilateur écrit en Haskell. Ou vraiment, ajoutez simplement une référence à l’appui de votre demande.
Vincent Savard

16
Même si les tortues sont tout en bas, PyPy ne pourrait exister sans un interpréteur Python écrit dans un autre langage.
Blrfl

18
@Birfl Mais ça ne dit pas grand chose. C n'aurait pas pu être écrit sans un compilateur d'assembly, et vous ne pouvez pas écrire d'assembly sans un matériel qui l'implémente.
Gardenhead

11
Si PyPy n'est pas un "langage de programmation système", car un compilateur C est impliqué quelque part, alors C n'est pas non plus un langage de programmation système, car un assembleur est utilisé quelque part. En fait, n'est-il pas populaire de traduire C dans une autre langue ces jours-ci? par exemple, LLVM

30

Désolé d'ajouter une autre réponse, mais je ne pense pas qu'aucune des réponses existantes adresse directement votre première phrase en ces termes:

'J'envisage d'apprendre C'

Pourquoi? Voulez-vous faire le genre de choses que C est habituellement utilisé aujourd'hui (par exemple, les pilotes de périphériques, les ordinateurs virtuels, les moteurs de jeu, les médiathèques, les systèmes intégrés, les noyaux de système d'exploitation)?

Si oui, alors oui, bien sûr, apprenez le C ou le C ++ en fonction de ceux qui vous intéressent. Voulez-vous l'apprendre de manière à mieux comprendre ce que fait votre langage de haut niveau?

Vous mentionnez ensuite les problèmes de sécurité. Vous ne devez pas nécessairement une profonde compréhension de la sécurité C faire ce dernier, de la même manière qu'un exemple de code dans une langue de niveau supérieur peut vous donner l'essentiel sans être prêt pour la production.

Ecrivez du code C pour comprendre l'essentiel. Puis remettez-le sur l'étagère. Ne vous inquiétez pas trop pour la sécurité, sauf si vous souhaitez écrire du code C de production .


2
Excellent travail pour répondre à ce qui semble être la vraie question! Un excellent moyen d’apprécier le langage C / C ++ et les langages "plus sûrs" est d’écrire quelque chose comme un simple moteur de base de données. Vous aurez une bonne idée de chacune des approches que vous essayez et verrez où cela vous mènera. Vous verrez ce qui semble naturel dans les deux cas, et vous verrez où l'approche naturelle échoue (par exemple, il est très facile de "sérialiser" des données brutes en C - écrivez simplement les données!; Mais le résultat n'est pas portable, alors peut être d'une utilité limitée). Comprendre la sécurité est délicat, car la plupart des problèmes peuvent être difficiles à résoudre.
Luaan

1
@Luaan exactement, apprendre à copier une chaîne à l'aide de pointeurs vous en donne l'idée. Apprendre à le faire en toute sécurité est un autre niveau et, en fonction de vos objectifs, un objectif peut-être inutile.
Jared Smith

2
Ce n'était pas vraiment la question. Mais c'était utile pour faire une dissision. J'ai décidé de le faire. Je suis disposé à en apprendre davantage sur le fonctionnement interne de tout ce qui est construit. Et j'aime juste programmer. De cette façon, j'espère mieux comprendre le fonctionnement interne des ordinateurs. C'est juste pour s'amuser.
Tristan

10
Je ne suis pas d'accord avec la dernière phrase. Apprenez comment faire les choses correctement avant de développer de mauvaises habitudes.
Glglgl

2
@glglgl IDK, si je lis (ou écris) un fragment de code JavaScript sur le Web, je le comprends en sachant qu'il n'est pas prêt pour la production: il ne comportera pas de gestion des exceptions, il pourra s'agir de O (n ^ 2), etc. de cela est nécessaire pour faire passer le message. Tout cela est nécessaire pour le code de production. Pourquoi est-ce différent? Je peux écrire un C naïf pour ma propre édification, tout en comprenant intellectuellement que si je voulais le publier, je devrais faire beaucoup plus de travail.
Jared Smith

14

C'est une question ÉNORME avec des tonnes de réponses, mais la version courte est que chaque langage de programmation est spécialisé pour différentes situations. Par exemple, JavaScript pour le Web, C pour les éléments de bas niveau, C # pour tout ce qui concerne Windows, etc. Il est utile de savoir ce que vous voulez faire une fois que vous connaissez la programmation pour choisir le langage de programmation à choisir.

Pour aborder votre dernier point, pourquoi C / C ++ sur Java / Python, il s’agit souvent de vitesse. Je crée des jeux, et Java / C # vient tout juste d’atteindre des vitesses suffisantes pour permettre aux jeux de fonctionner. Après tout, si vous voulez que votre jeu fonctionne à 60 images par seconde et que votre jeu en fasse beaucoup (le rendu est particulièrement coûteux), vous avez besoin que le code soit exécuté le plus rapidement possible. Python / Java / C # / Beaucoup d'autres utilisent des "interpréteurs", une couche logicielle supplémentaire qui gère tout ce qui est fastidieux, contrairement au C / C ++, comme la gestion de la mémoire et le garbage collection. Cette surcharge supplémentaire ralentit les choses, de sorte que presque tous les grands jeux que vous voyez ont été réalisés (au cours des 10 dernières années, en tout cas) en C ou C ++. Il existe des exceptions: le moteur de jeu Unity utilise C # * et Minecraft utilise Java, mais ce sont des exceptions et non des règles. En général,

* Même Unity n’est pas tout en C #, d’énormes morceaux le sont en C ++ et vous utilisez simplement C # pour votre code de jeu.

EDIT Pour répondre à certains des commentaires qui se sont manifestés après avoir posté ceci: Peut-être que je simplifiais trop, je ne faisais que brosser un tableau général. Avec la programmation, la réponse n’est jamais simple. Il existe des interprètes pour le langage C, Javascript peut fonctionner en dehors du navigateur et C # peut fonctionner à peu près avec n'importe quoi grâce à Mono. Différents langages de programmation sont spécialisés pour différents domaines, mais certains programmeurs ont probablement compris comment faire en sorte que n'importe quel langage s'exécute dans n'importe quel contexte. Comme le PO semblait ne pas connaître beaucoup de programmation (supposition de ma part, désolé si je me trompe), j'essayais de garder ma réponse simple.

Quant aux commentaires sur le fait que C # soit presque aussi rapide que C ++, le mot clé est presque. Lorsque j'étais à l'université, nous avons visité de nombreuses sociétés de jeu. Mon professeur (qui nous avait encouragé à passer de C # à C ++ toute l'année) a demandé aux programmeurs de chaque société que nous consultions pourquoi C ++ plutôt que C #. dit C # est trop lent. En général, il fonctionne rapidement, mais le ramasse-miettes peut nuire aux performances car vous ne pouvez pas contrôler son exécution, et il a le droit de vous ignorer s'il ne veut pas s'exécuter lorsque vous le recommandez. Si vous avez besoin que quelque chose soit de haute performance, vous ne voulez pas de quelque chose d'aussi imprévisible que cela.

Pour répondre à mon commentaire "juste pour atteindre des vitesses", oui, une grande partie de l'augmentation de la vitesse de C # provient d'un meilleur matériel, mais avec l'amélioration du framework .NET et du compilateur C #, certaines accélérations ont été enregistrées.

À propos du commentaire "les jeux sont écrits dans la même langue que le moteur", cela dépend. Certains le sont, mais beaucoup sont écrits dans un hybride de langues. Unreal peut faire UnrealScript et C ++, Unity utilise C # Javascript et Boo, de nombreux autres moteurs écrits en C ou C ++ utilisent Python ou Lua comme langages de script. Il n'y a pas de réponse simple ici.

Et juste parce que cela me dérange de lire "qui se soucie de savoir si votre jeu tourne à 200fps ou 120fps", si votre jeu tourne plus vite que 60fps, vous perdez probablement du temps CPU, car le moniteur moyen ne rafraîchit même pas cela vite. Certains haut de gamme et les plus récents font, mais ce n'est pas standard (pour le moment ...).

Et à propos de la remarque "ignorant des décennies de technologie", je suis encore dans la vingtaine, alors quand j'extrapole en arrière, je fais principalement écho à ce que des programmeurs plus âgés et plus expérimentés m'ont dit. Évidemment, ce sera contesté sur un site comme celui-ci, mais sa mérite d'être considéré.


4
" C # pour tout ce que Windows " - Oh, c'est une telle erreur. Et vous donnez même un exemple. Unité. Autant que je sache, ce n'est pas écrit, il fournit une API C # car le langage est agréable et adaptable. C'est vraiment bien conçu. Et j'aime plus c ++, mais le crédit devrait être donné là où il est dû. Peut-être avez-vous mélangé C # avec .NET? Ils traînent ensemble assez souvent.
luk32

2
"Même Unity n’est pas tout en C #, d’énormes morceaux le sont en C ++" Et? Les jeux dans Unity utilisent souvent beaucoup C # et existent depuis un certain temps déjà. Suggérer que C # n'atteint «que récemment les vitesses» a besoin de davantage de contexte ou risque d'être aveugle aux technologies de ces dernières décennies.
NPSF3000

2
Presque tous les gros jeux étaient écrits dans la langue du moteur utilisé: la quantité de travail à dupliquer aurait été si importante qu'aucun autre aspect technique ne méritait d'être pris en compte. Le rendu est certes coûteux, mais de nos jours, tout est écrit en shaders et le langage de la boucle logique n’est pas pertinent.
Peter Taylor

2
C # a toujours été compilé au format JIT (contrairement à Java, où votre commentaire est correct), et il était tout à fait capable de vitesses d’exécution très similaires à C ++ dès le départ si vous saviez ce que vous faisiez. C'est 2003 - pas quelque chose que je considérerais comme récent. La vitesse brute n’est pas le principal problème des jeux (en particulier avec les shaders programmables sur le GPU), il existe d’autres facteurs qui ont parfois rendu les langages comme C # plus ou moins populaires. Les deux principaux problèmes sont les API (qui sont fortement orientées C et l’interfaçage peuvent être coûteux) et le GC (principalement pour les problèmes de latence, et non pour le débit brut).
Luaan

1
@gbjbaanb Il n'y a pas que les processeurs qui sont plus rapides. C’est un gros problème: C ++ et C ont mis des décennies à perfectionner leurs compilateurs et leur environnement d’exécution, tandis que Java a pratiquement démarré de zéro (conçu essentiellement comme une plate-forme multi-plateforme). Au fur et à mesure de l'amélioration de la machine virtuelle (passage d'interprète à un compilateur JIT, amélioration du GC, etc.), les performances des applications Java s'amélioraient. Une grande partie de l'avantage C / C ++ réside toujours dans l'approche "espérons que rien ne casse" - en évitant de nombreuses vérifications jugées "inutiles". Mais c'est
quand

13

C’est drôle que vous affirmiez que C n’est pas sûr, car "il a des indicateurs". Le contraire est vrai: Java et C # n’ont pratiquement que des pointeurs (pour les types non natifs). L’erreur la plus courante en Java est probablement l’exception de pointeur nul (cf. https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare ). La deuxième erreur la plus courante consiste probablement à conserver des références cachées à des objets inutilisés (par exemple, les dialogues fermés ne sont pas supprimés), qui ne peuvent donc pas être libérées, ce qui conduit à des programmes de longue durée avec une empreinte mémoire toujours croissante.

Il existe deux mécanismes de base qui rendent C # et Java plus sûrs et plus sûrs de deux manières différentes:

  • Le ramassage des ordures diminue le risque que le programme tente d'accéder aux objets rejetés. Cela rend le programme moins susceptible de se terminer de manière inattendue. Contrairement à C, Java et C # par défaut allouent des données non natives de manière dynamique. Cela rend en réalité la logique du programme plus complexe, mais le ramassage des ordures intégré - à un coût - prend le relais.

Les pointeurs intelligents récents du C ++ facilitent ce travail pour les programmeurs.

  • Java et C # se compilent en un code intermédiaire interprété / exécuté par un temps d'exécution élaboré. Cela ajoute un niveau de sécurité car l'exécution peut détecter des activités illicites d'un programme. Même si le programme est codé de manière non sécurisée (ce qui est possible dans les deux langues), le temps d’exécution correspondant en théorie empêche toute "insertion" dans le système.
    Le temps d'exécution ne protège pas contre, par exemple, les tentatives de dépassement de mémoire tampon, mais n'autorise théoriquement pas les exploits de tels programmes. En C et C ++, en revanche, le programmeur doit coder de manière sécurisée afin d'empêcher les exploits. Ce n'est généralement pas réalisé tout de suite, mais nécessite des révisions et des itérations.

Il convient de noter cependant que le temps d'exécution complexe constitue également un risque pour la sécurité. Il me semble qu'Oracle met à jour la machine virtuelle Java toutes les deux semaines en raison de problèmes de sécurité récemment découverts. Bien entendu, il est beaucoup plus difficile de vérifier la JVM qu’un seul programme.

La sécurité d’une durée d’exécution complexe est donc ambiguë et décevante: votre programme C moyen peut, avec des examens et des itérations, être raisonnablement sécurisé. Votre programme Java moyen est aussi sécurisé que la machine virtuelle Java; c'est pas vraiment. Jamais.

L'article à propos gets()duquel vous créez un lien reflète les décisions des bibliothèques historiques qui seraient prises différemment aujourd'hui, pas la langue principale.


3
Je pense que le point de l'auteur original est qu'en C vous êtes capable de prendre des mesures non contrôlées sur ces pointeurs. En Java, vous obtenez tout de suite une belle exception: en C, vous ne réaliserez peut-être pas que vous lisez un emplacement non valide tant que l'état de votre application n'est pas corrompu.
Sam Dufel

1
En outre, stackoverflow.com/questions/57483/… - il serait plus exact de dire que java n'a "pratiquement que des références".
Sam Dufel

4
J'ai vu toutes sortes de bugs intéressants résulter d'essais d'éviter les pointeurs explicites. Généralement, le problème fondamental est la confusion entre copie et référence. En C, si je vous passe un pointeur sur quelque chose, vous savez que le modifier affectera l'original. Certaines des tentatives pour éviter les pointeurs obscurcissent cette distinction, conduisant à un labyrinthe de copies profondes, de copies superficielles et de confusion générale.
Arlie Stephens

Affirmer que la machine virtuelle Java d’Oracle est nul (du point de vue des vulnérabilités de sécurité exploitables hémorragiques) et que, par conséquent, les runtimes des langages gérés introduisent plus de problèmes de sécurité que l’utilisation d’un langage géré évite revient à dire qu'Adobe Flash est une source d'insécurité épouvantable et Est-ce que la lecture de vidéos et d'animations à partir d'un site Web doit être intrinsèquement ridicule? Toutes les exécutions de Java ne sont pas aussi mauvaises que l'abomination de la JVM des années 1990 appartenant à Oracle / Sun et tous les langages gérés ne sont pas Java. (Eh bien, évidemment.)
majeure partie informée

@halfinformed Well; Je disais qu'un programme est aussi sécurisé que son exécution, et que votre programme "moyen" (lire: small-ish) peut être rendu plus sûr que n'importe quelle exécution longue comme un interpréteur de code octet. Cette déclaration semble indéniable. La sécurité d’un programme autonome donné ou de son exécution particulière dépend de la complexité, de la conception, du codage et de la qualité de la maintenance de chacun. Par exemple, je ne dirais pas que sendmail est plus sécurisé que la machine virtuelle Java d'Oracle; mais qmail peut être.
Peter A. Schneider

10

Parce que la "sécurité" coûte de la vitesse, les langages "plus sûrs" fonctionnent à une vitesse plus lente.

Vous demandez pourquoi utiliser un langage "dangereux" comme le C ou C ++, demander à quelqu'un de vous écrire un pilote vidéo ou similaire en Python ou en Java, etc. et voir comment vous vous sentez à propos de la "sécurité" :)

Sérieusement, vous devez être aussi proche de la mémoire centrale de la machine pour pouvoir manipuler les pixels, les registres, etc. Java ou Python ne peuvent le faire avec aucun type de vitesse digne de la performance ... C et C ++. vous permet de le faire à travers des pointeurs, etc.


20
Ce n'est pas vrai en général que la sécurité coûte la vitesse . Les langues disponibles les plus sûres effectuent la plupart des vérifications au moment de la compilation. O'Caml, Ada, Haskell, Rust ne sont pas en retard sur C en termes de vitesse d'exécution moyenne. Ce qu'ils ne sont habituellement assujettis est une surcharge significative dans la taille du programme, l' efficacité de la mémoire, la latence et la compilation évidemment du temps. Et, oui, ils ont des difficultés avec des choses proches du métal. Mais ce n'est pas vraiment un problème de vitesse.
gauche autour du

6
De plus, C ne fait pas ce que vous pensez. C est une machine abstraite . Cela ne vous donne aucun accès direct à quelque chose - c'est une bonne chose. Vous ne pouvez même pas regarder un assemblage moderne pour voir combien de C vous cache, l'assemblage moderne (par exemple, TASM) aurait été considéré comme un langage de haut niveau dès le développement de C. Je serais très heureux si quelqu'un écrivait des pilotes dans une langue "sûre", merci - cela aiderait à éviter beaucoup de ces BSOD et des blocages, sans parler des failles de sécurité :) Et surtout, il y a des langages systèmes beaucoup plus sûrs que C.
Luaan

3
@Wintermute Vous voulez vraiment regarder Rust avant de faire des commentaires sur le coût de la rapidité des fonctions de sécurité. En fait, le système de types bas niveau de C empêche en fait de nombreuses optimisations très utiles que les compilateurs pourraient réaliser (en particulier si l’on considère qu’aucun grand projet c ne parvient à ne pas violer l’aliasing strict quelque part ).
Voo le

7
@Wintermute Ouais, le mythe selon lequel on ne peut pas rendre le C / C ++ plus sûr sans introduire un surcoût de performance est très persistant, c'est pourquoi je considère cela comme plutôt grave (il y a des domaines où cela est certainement vrai [vérification des limites]). Maintenant, pourquoi la rouille n'est-elle pas plus répandue? Histoire et complexité. Rust est encore relativement nouveau et de nombreux systèmes parmi les plus grands écrits en C existaient déjà avant l’invention de Rust. Vous n’allez pas réécrire un million de LOC dans une nouvelle langue, même si elle était beaucoup plus sûre. De plus, chaque programmeur et son chien connaissent C, Rust? Bonne chance pour trouver assez de personnes.
Voo le

3
@Voo Dogs faisant C? ... pas étonnant que j'ai vu tant de mauvais code là-bas ... j / k Point pris à propos de Rust (je viens de le télécharger et de l'installer, donc vous pouvez avoir un autre convert à ajouter) BTW en ce qui concerne à Rust le faire correctement ... Je pourrais faire la même augmentation pour "D" :)
Wintermut3

9

Outre tout ce qui précède, il existe également un cas d'utilisation assez courant, qui utilise C comme bibliothèque commune pour d'autres langues.

Fondamentalement, presque toutes les langues ont une interface API pour C.

Exemple simple, essayez de créer une application commune pour Linux / IOS / Android / Windows. Outre tous les outils existants, nous avons fini par créer une bibliothèque principale en C, puis de modifier l'interface graphique pour chaque environnement, à savoir:

  • IOS: ObjectiveC peut utiliser les bibliothèques C de manière native
  • Android: Java + JNI
  • Linux / Windows / MacOS: Avec GTK / .Net, vous pouvez utiliser des bibliothèques natives. Si vous utilisez Python, Perl, Ruby, chacun d'entre eux possède des interfaces d'API natives. (Java à nouveau avec JNI).

Mes deux centimes,


L’une des raisons pour lesquelles j’aime utiliser, disons, PHP, c’est que presque toutes ses bibliothèques sont en effet écrites en C - heureusement, sinon, PHP serait insupportablement lent :) PHP est génial pour écrire du code bâclé sans crainte de faire quelque chose de "dangereux" (et c'est pourquoi j'ai tendance à écrire beaucoup plus de code PHP qu'autre chose - j'aime le code bâclé!: D), mais il est bon de savoir que beaucoup de ces appels de fonction contiennent le bon vieux "fidèle" Des bibliothèques C pour améliorer ses performances ;-) En revanche, écrire du code bâclé en C est un gros non-droit ...
Gwyneth Llewelyn

7

Une difficulté fondamentale avec C est que le nom est utilisé pour décrire un certain nombre de dialectes avec une syntaxe identique mais une sémantique très différente. Certains dialectes sont beaucoup plus sûrs que d'autres.

En C tel que conçu à l'origine par Dennis Ritchie, les instructions C seraient généralement associées aux instructions machine de manière prévisible. Parce que C pouvait fonctionner sur des processeurs qui se comportaient différemment lorsque des événements tels que le débordement arithmétique signé se produisaient, un programmeur qui ne savait pas comment se comporterait une machine en cas de débordement arithmétique ne saurait savoir quel code C s'exécutant sur cette machine se comporterait également, mais si une machine était connue pour se comporter d'une certaine manière (par exemple, un enveloppement de complément à deux silencieux), les implémentations sur cette machine feraient généralement de même. L’une des raisons pour lesquelles C s’est acquis la réputation d’être rapide, c’est que dans les cas où les programmeurs savaient que le comportement naturel d’une plate-forme dans des scénarios de cas extrêmes correspondait à leurs besoins, le programmeur ou le compilateur n’avait pas besoin d’écrire du code pour générer de tels scénarios. .

Malheureusement, les rédacteurs de compilateurs ont estimé que, puisque la Norme n’imposait aucune exigence quant aux implémentations à effectuer dans de tels cas (un laxisme destiné à permettre des implémentations matérielles qui pourraient ne pas se comporter de manière prévisible), les compilateurs devraient se sentir libres de générer du code non conforme aux lois. de temps et de causalité.

Considérons quelque chose comme:

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

La théorie du compilateur hyper moderne (mais à la mode) suggère que le compilateur devrait produire "QUACK!" inconditionnellement, puisque dans tous les cas où la condition était fausse, le programme finirait par invoquer un comportement indéfini en effectuant une multiplication dont le résultat serait de toute façon ignoré. Etant donné que la norme autoriserait un compilateur à faire tout ce qu’elle voudrait dans un tel cas, elle lui permet d’afficher "QUACK!".

Alors que C était autrefois plus sûr que le langage assembleur, l’inverse est vrai lors de l’utilisation de compilateurs hyper-modernes. En langage assembleur, le dépassement d’entier peut faire en sorte que le calcul produise un résultat dénué de sens, mais sur la plupart des plateformes, ce sera l’étendue de ses effets. Si les résultats finissent par être ignorés de toute façon, le débordement n'aura pas d'importance. Dans le C hyper moderne, cependant, même ce qui serait normalement des formes "bénignes" de comportement indéfini (comme un dépassement d'entier dans un calcul qui finit par être ignoré) peut provoquer l'exécution arbitraire du programme.


1
même dans un compilateur hyper-moderne, C ne vérifie pas les tableaux. si tel était le cas, cela ne serait pas compatible avec la définition de la langue. J'utilise parfois ce fait pour faire des tableaux avec un pointeur supplémentaire au milieu du tableau pour avoir des indices négatifs.
robert bristow-johnson

1
J'aimerais voir des preuves de votre exemple produisant "QUACK!" sans condition. x peut certainement être supérieur à 1000000 au point de comparaison, et une évaluation ultérieure qui aboutirait à un débordement ne l'empêche pas. Plus encore, si vous avez activé l'inline qui permet de supprimer la multiplication de débordement, votre argument concernant les restrictions de plage implicites ne tient pas.
Graham

2
@ robertbristow-johnson: En fait, la norme dit très explicitement que int arr[5][[5], par exemple , une tentative d'accès arr[0][5]produira un comportement non défini. Une telle règle permet à un compilateur de arr[1][0]=3; arr[0][i]=6; arr[1][0]++;pouvoir en déduire que sa valeur arr[1][0]sera égale à 4, sans tenir compte de la valeur de i.
Supercat

2
@ robertbristow-johnson: Même si le compilateur alloue des tableaux dans une structure de manière séquentielle sans espace, cela ne garantit pas que l'indexation de l'un des tableaux aura nécessairement une incidence sur une autre. Voir godbolt.org/g/Avt3KW pour un exemple de la façon dont gcc traitera ce code.
Supercat

1
@ robertbristow-johnson: J'ai commenté l'assemblée pour expliquer son travail. Le compilateur voit que le code enregistre 1 dans s-> arr2 [0], puis incrémente s-> arr2 [0]. Gcc combine donc ces deux opérations en faisant simplement en sorte que le code enregistre la valeur 2, sans tenir compte du risque d'écriture s-> arr1 [i] peut affecter la valeur de s-> arr1 [0] (puisque, selon la norme, cela ne peut pas).
Supercat

5

Raisons historiques. Je ne parviens pas souvent à écrire un nouveau code, mais surtout à entretenir et à étendre le vieil outil utilisé depuis des décennies. Je suis juste content que ce soit C et pas Fortran.

Je peux m'énerver quand un élève dit: "Mais pourquoi diable faites-vous cet horrible X alors que vous pourriez faire Y?". Eh bien, X est mon travail et il paie très bien les factures. J'ai fait Y à l'occasion, et c'était amusant, mais X est ce que la plupart d'entre nous font.


5

Qu'est-ce qui est "dangereux"?

L’affirmation selon laquelle «C» est «dangereux» est un sujet de discussion fréquent dans les guerres de flammes de langage (le plus souvent par rapport à Java). Cependant, les preuves de cette affirmation ne sont pas claires.

C est une langue avec un ensemble particulier de fonctionnalités. Certaines de ces fonctionnalités peuvent autoriser certains types d'erreurs qui ne sont pas autorisés par d'autres types de langages (les risques de gestion de la mémoire de C sont généralement mis en évidence). Cependant, cela n’est pas la même chose qu’un argument selon lequel C est plus dangereux que les autres langues en général . Je ne connais personne qui ait fourni des preuves convaincantes sur ce point.

En outre, le terme "dangereux" dépend du contexte: qu'essayez-vous de faire et quels types de risques vous inquiètent-ils?

Dans de nombreux contextes, j'estime que C est plus "dangereux" qu'un langage de haut niveau, car il nécessite une implémentation plus manuelle des fonctionnalités de base, ce qui augmente le risque de bugs. Par exemple, effectuer un traitement de texte de base ou développer un site Web en C serait généralement idiot, car les autres langues ont des fonctionnalités qui facilitent grandement cette tâche.

Cependant, C et C ++ sont largement utilisés pour les systèmes critiques, car un langage plus petit avec un contrôle plus direct de hardward est considéré comme "plus sûr" dans ce contexte. D' une très bonne réponse Stack Overflow :

Bien que C et C ++ n'aient pas été conçus spécifiquement pour ce type d'application, ils sont largement utilisés pour les logiciels intégrés et critiques pour la sécurité pour plusieurs raisons. Les principales propriétés de note sont le contrôle de la gestion de la mémoire (ce qui vous permet d'éviter d'avoir à nettoyer, par exemple), des bibliothèques d'exécution simples, bien déboguées et un support pour les outils développés. Un grand nombre des chaînes d'outils de développement intégrées utilisées aujourd'hui ont été développées pour la première fois dans les années 1980 et 1990, alors qu'il s'agissait de la technologie actuelle. Elles proviennent de la culture Unix qui prévalait à cette époque. Ces outils restent donc populaires pour ce type de travail.

Le code de gestion manuelle de la mémoire doit être soigneusement vérifié pour éviter les erreurs, mais il permet un contrôle des temps de réponse des applications qui n’est pas disponible dans les langues dépendantes du garbage collection. Les principales bibliothèques d'exécution des langages C et C ++ sont relativement simples, matures et bien comprises. Elles font donc partie des plates-formes les plus stables disponibles.


2
Je dirais que le C hyper-moderne est également plus dangereux que le langage d'assemblage ou les véritables dialectes du C de bas niveau qui se comportent toujours comme s'ils traduisaient systématiquement les opérations du C en opérations de code machine sans tenir compte des cas extrêmes où les opérations de code machine naturel comportement défini, mais la norme C n’imposerait aucune exigence. L'approche hyper-moderne où un dépassement d'entier peut annuler les règles du temps et la causalité semble beaucoup moins susceptible de générer un code sécurisé.
Supercat

5

Pour ajouter aux réponses existantes, il est bon de dire que vous allez choisir Python ou PHP pour votre projet, en raison de leur sécurité relative. Mais quelqu'un doit implémenter ces langages et, quand ils le feront, ils le feront probablement en C. (Ou alors, quelque chose du genre.)

C'est pourquoi les gens utilisent C - pour créer les outils les moins dangereux que vous souhaitez utiliser.


2

Permettez-moi de reformuler votre question:

J'envisage d'apprendre [outil].

Mais pourquoi les gens utilisent-ils [outil] (ou [outil associé]) s’ils [peuvent] être utilisés «dangereusement»?

Tout outil intéressant peut être utilisé dangereusement, y compris les langages de programmation. Vous en apprendrez plus pour pouvoir faire plus (et ainsi, vous créerez moins de danger lorsque vous utiliserez l'outil). En particulier, vous apprenez à utiliser l'outil pour pouvoir faire la chose pour laquelle cet outil est bon (et peut-être reconnaître que cet outil est le meilleur outil parmi ceux que vous connaissez).

Par exemple, si vous devez insérer un trou cylindrique de 6 mm de diamètre et de 5 cm de profondeur dans un bloc de bois, une perceuse est un outil bien meilleur qu'un analyseur LALR. Si vous savez quels sont ces deux outils, vous savez quel est le bon outil. Si vous savez déjà comment utiliser une perceuse, voila !, hole.

C est juste un autre outil. C'est mieux pour certaines tâches que pour d'autres. Les autres réponses ici traitent de cela. Si vous apprenez un peu de C, vous en arriverez à reconnaître quand c'est le bon outil et quand il ne l'est pas.


Cette réponse explique pourquoi les questions sont jetées comme "principalement basées sur l'opinion". Ne dites pas que C a ses avantages, dites ce qu'ils sont!
Reinierpost

1

J'envisage d'apprendre C

Il n'y a pas de raison spécifique de ne pas apprendre le C, mais je suggérerais le C ++. Il offre une grande partie de ce que fait C (puisque C ++ est un super ensemble de C), avec une grande quantité de "suppléments". Apprendre C avant C ++ n'est pas nécessaire - ce sont en réalité des langages séparés.

En d'autres termes, si C était un ensemble d'outils pour le travail du bois, ce serait probablement:

  • marteau
  • ongles
  • scie à main
  • perceuse à main
  • ponceuse
  • ciseau (peut-être)

Vous pouvez construire n'importe quoi avec ces outils - mais tout ce qui est bien nécessite potentiellement beaucoup de temps et de compétences.

C ++ est la collection d'outils électriques de votre quincaillerie locale.

Si vous vous en tenez aux fonctionnalités de base du langage, C ++ a relativement peu de courbe d'apprentissage supplémentaire.

Mais pourquoi les gens utilisent-ils C (ou C ++) s’il peut être utilisé «dangereusement»?

Parce que certaines personnes ne veulent pas de meubles IKEA. =)

Sérieusement, bien que de nombreux langages "plus élevés" que le C ou le C ++ puissent avoir des choses qui les rendent (potentiellement) "plus faciles" à utiliser dans certains aspects, ce n'est pas toujours une bonne chose. Si vous n'aimez pas la façon dont quelque chose est fait ou une fonctionnalité n'est pas fournie, vous ne pourrez probablement rien faire à ce sujet. D'autre part, C et C ++ fournissent suffisamment de fonctionnalités de langage "bas niveau" (y compris des pointeurs) pour que vous puissiez accéder directement à beaucoup de choses (matériel ou système d'exploitation) ou les construire vous-même, ce qui peut ne pas être possible dans d'autres cas. langues mises en œuvre.

Plus spécifiquement, C possède les fonctionnalités suivantes qui le rendent souhaitable pour de nombreux programmeurs:

  • Vitesse - En raison de sa simplicité relative et des optimisations du compilateur au fil des ans, il est très rapide en mode natif. En outre, beaucoup de gens ont trouvé beaucoup de raccourcis vers des objectifs spécifiques lors de l'utilisation du langage, ce qui le rend potentiellement encore plus rapide.
  • Taille - Pour des raisons similaires à celles indiquées pour la vitesse, les programmes C peuvent être très réduits (à la fois en termes de taille d’exécutable et d’utilisation de la mémoire), ce qui est souhaitable pour les environnements à mémoire limitée (intégrée ou mobile).
  • Compatibilité - C existe depuis longtemps et tout le monde a des outils et des bibliothèques pour le faire. Le langage lui-même n'est pas difficile non plus - il s'attend à ce qu'un processeur exécute des instructions et que la mémoire détienne des éléments, et c'est à peu près tout.

    En outre, il existe quelque chose appelé une interface binaire d'application (ABI) . En bref, c'est un moyen pour les programmes de communiquer au niveau du code machine, ce qui peut présenter des avantages par rapport à une API (Application Programming Interface) . Tandis que d'autres langages tels que C ++ peuvent avoir une ABI, ils sont généralement moins uniformes (accord) que le C, donc C est un bon langage de base lorsque vous souhaitez utiliser une ABI pour communiquer avec un autre programme pour une raison quelconque.

Pourquoi les programmeurs n'utilisent-ils pas simplement Java ou Python ou un autre langage compilé tel que Visual Basic?

Efficacité (et parfois schémas de gestion de la mémoire impossibles à mettre en œuvre sans un accès relativement direct à la mémoire).

Accéder directement à la mémoire avec des pointeurs présente de nombreux trucs astucieux (généralement rapides) quand vous pouvez mettre vos pattes sales sur les petits et les zéros dans vos coffres de mémoire directement sans avoir à attendre que ce méchant professeur vous distribue les jouets au moment de la lecture, ramassez-les à nouveau.

En bref, ajouter des éléments crée potentiellement un décalage ou introduit une complexité indésirable.

En ce qui concerne les langages de script et autres logiciels similaires, vous devez travailler dur pour que les langages nécessitant des programmes secondaires s'exécutent aussi efficacement que C (ou tout autre langage compilé) le font de manière native. L'ajout d'un interpréteur à la volée introduit de manière inhérente la possibilité d'une vitesse d'exécution réduite et d'une utilisation accrue de la mémoire, car vous ajoutez un autre programme au mixage. L’efficacité de votre programme dépend autant de l’efficacité de ce programme secondaire que de la qualité (mal = =) de votre code de programme original. Sans parler de votre programme est souvent complètement dépendant du second programme pour même exécuter. Ce second programme n'existe pas pour une raison quelconque sur un système particulier? Code no go.

En fait, introduire quelque chose d’ extra ralentit ou complique potentiellement votre code. Dans les langues "sans indicateurs effrayants", vous attendez toujours que d'autres morceaux de code soient nettoyés ou que vous trouviez autrement des façons "sûres" de faire les choses, car votre programme effectue toujours les mêmes opérations d'accès à la mémoire qu'avec d'autres méthodes. pointeurs. Vous n'êtes simplement pas celui qui le gère (vous ne pouvez donc pas le faire, génie = P).

Par dangereux, je veux dire avec des pointeurs et autres choses similaires. [...] Comme pour la question du débordement de pile Pourquoi la fonction d'obtention est-elle si dangereuse qu'elle ne devrait pas être utilisée?

Selon la réponse acceptée:

"Cela restait une partie officielle du langage jusqu'à la norme ISO C 1999, mais il a été officiellement supprimé par la norme 2011. La plupart des implémentations C le supportent toujours, mais au moins gcc envoie un avertissement pour tout code qui l'utilise."

L'idée que, parce que quelque chose peut être fait dans une langue, il faut le faire est stupide. Les langues ont des défauts qui sont corrigés. Pour des raisons de compatibilité avec du code plus ancien, cette construction peut toujours être utilisée. Mais rien n'oblige (probablement) un programmeur à utiliser gets () et, en fait, cette commande a essentiellement été remplacée par des alternatives plus sûres.

Plus précisément, le problème avec gets () n'est pas un problème de pointeur en soi. C'est un problème avec une commande qui ne sait pas nécessairement comment utiliser la mémoire en toute sécurité. Dans un sens abstrait, tout est question de pointeur - lire et écrire des choses que vous n’êtes pas supposée faire. Ce n'est pas un problème avec les pointeurs; c'est un problème d'implémentation de pointeur.

Pour clarifier, les pointeurs ne sont pas dangereux tant que vous n'avez pas accédé accidentellement à un emplacement de mémoire auquel vous n'aviez pas l'intention. Et même dans ce cas, cela ne garantit pas que votre ordinateur va fondre ou exploser. Dans la plupart des cas, votre programme ne fonctionnera plus (correctement).

Cela dit, étant donné que les pointeurs fournissent un accès aux emplacements de mémoire et que les données et le code exécutable existent en mémoire, il existe un risque réel de corruption accidentelle pour que vous souhaitiez gérer correctement la mémoire.

Parce que les opérations d’accès direct à la mémoire offrent généralement généralement moins d’avantages qu’il ya des années, même les langages non chiffrés comme C ++ ont introduit des fonctionnalités telles que les pointeurs intelligents pour aider à combler le fossé entre efficacité de la mémoire et sécurité.

En résumé, il y a très peu de raisons de craindre le pointeur tant qu'il est utilisé en toute sécurité. Prenez juste un indice de la version de South Park de Steve "The Crocodile Hunter" Irwin - ne vous fourrez pas le pouce dans les trous des crocs .


2
Je ne suis pas d'accord avec la suggestion d'apprendre le C ++ à la place du C. Écrire un bon C ++ est plus difficile que d'écrire un bon C et lire C ++ est beaucoup plus difficile que de lire C. La courbe d'apprentissage du C ++ est donc beaucoup plus raide. "C ++ est un super jeu de C" Cela revient plus ou moins à dire que les bottes sont un sur-ensemble de pantoufles. Ils ont des avantages et des usages différents et chacun présente des caractéristiques que l’autre n’a pas.
martinkunev

"Écrire un bon C ++ est plus difficile qu'écrire un bon C" - Absolument. =) "[C] est plus difficile de lire le C ++ que de lire le C" - Toute programmation avancée est probablement indiscernable de la magie ;-) Mes deux cents sont que cela dépend beaucoup plus du programmeur que du langage, bien que C ++ ne fasse pas grand chose pour s'aider dans cette catégorie. "La courbe d’apprentissage du C ++ est donc beaucoup plus raide." - A long terme, oui. À court terme, moins (à mon avis). De manière anecdotique, la plupart des cours de langues de base en C et C ++ sont susceptibles de couvrir à peu près les mêmes types généraux de matériel, à l'exception des cours en C ++.
Anaksunaman

2
"Ils ont des avantages et des usages différents et chacun présente des caractéristiques que l’autre n’a pas." - Comme mentionné "Il n’ya aucune raison spécifique de ne pas apprendre le C [.]" C est un beau langage et je m'en tiens à cela. Si cela convient à OP ou à quelqu'un d'autre, j'appuie entièrement son apprentissage. =)
Anaksunaman

L'apprentissage C vous apprend le fonctionnement de la machine (pas tout en bas, mais tout de même un peu plus près du métal). C'est une très bonne raison pour l'apprendre.
Agent_L

1

Comme toujours, le langage de programmation n’est qu’une conséquence de la résolution de problèmes. En fait, vous devriez apprendre non seulement le C, mais de nombreux langages (et d'autres méthodes de programmation d'un ordinateur, qu'il s'agisse d'outils d'interface graphique ou d'interpréteurs de commandes) pour disposer d'une boîte à outils décente à utiliser pour résoudre des problèmes.

Parfois, vous constaterez qu'un problème se prête bien à quelque chose qui est inclus dans les bibliothèques Java par défaut. Dans ce cas, vous pouvez choisir Java pour tirer parti de cela. Dans d’autres cas, il se peut que vous deviez faire quelque chose de Windows beaucoup plus simple dans le runtime .NET, vous pouvez donc utiliser C # ou VB. Il pourrait y avoir un outil graphique ou un script de commande qui résout votre problème, vous pouvez alors les utiliser. Peut-être avez-vous besoin d'écrire une application graphique sur plusieurs plates-formes. Java pourrait être une option, étant donné les bibliothèques incluses dans le JDK, mais là encore, une plate-forme cible peut être dépourvue d'un JRE, vous pouvez donc choisir plutôt C et SDL (ou similaire).

C occupe une place importante dans cet ensemble d'outils, car il est général, petit et rapide et compile également en code machinable. Il est également supporté sur toutes les plateformes sous le soleil (non sans recompiler cependant).

En bout de ligne, vous devriez apprendre autant d’outils, de langues et de paradigmes que possible.

Veuillez vous écarter de l’état d’esprit: "Je suis un programmeur X" (X = C, C ++, Java, etc.)

Il suffit d'utiliser "Je suis un programmeur".

Un programmeur résout des problèmes et conçoit des algorithmes en demandant aux machines d’effectuer la charge de travail. Fin de l'histoire. Ceci est sans rapport avec la langue. Votre compétence la plus importante est la résolution de problèmes et la décomposition logique de problèmes structurés, la compétence / le choix de la langue est TOUJOURS secondaire et / ou une conséquence de la nature du problème.

Un chemin intéressant si vous êtes intéressé par C est d’étendre vos compétences avec Go. Go est vraiment un C amélioré, avec un ramasse-miettes et des interfaces, ainsi qu’un modèle / canaux de threading intégré, qui apporte également de nombreux avantages du C (tels que l’arithmétique de pointeur et la compilation en code machine).


0

Cela dépend de ce que vous avez l'intention de faire avec. C a été conçu pour remplacer le langage assembleur et est le langage de haut niveau le plus proche du langage machine. Ainsi, sa taille et ses performances sont peu élevées, et convient parfaitement à la programmation système et à d’autres tâches nécessitant un faible encombrement et se rapprochant du matériel sous-jacent.


0

Lorsque vous travaillez au niveau des bits et des octets, de la mémoire en tant que collecte brute de données homogène, comme il serait souvent nécessaire de mettre en œuvre efficacement les allocateurs et les structures de données les plus efficaces, aucune sécurité n'est à craindre. La sécurité est principalement un concept fort lié au type de données, et un allocateur de mémoire ne fonctionne pas avec les types de données. Il fonctionne avec des bits et des octets à regrouper avec ces mêmes bits et octets représentant potentiellement un type de données à un moment donné et un autre plus tard.

Peu importe si vous utilisez C ++ dans ce cas. Vous seriez toujours en train de saupoudrer static_caststout le code pour créer des void*pointeurs et continuer à travailler avec des bits et des octets et à gérer plus de soucis liés au respect du système de types dans ce contexte que C qui possède un système de types beaucoup plus simple où vous êtes libre. en memcpybits et en octets sans se soucier de la suppression au bulldozer du système de types.

En fait, il est souvent plus difficile de travailler en C ++, un langage globalement plus sûr, dans des contextes de bits et d'octets de bas niveau sans écrire du code encore plus dangereux qu'en C, car écraser les vptr et ne pas appeler les constructeurs et les destructeurs de copie aux moments appropriés. Si vous prenez le temps de respecter ces types et d'utiliser le placement, puis d'invoquer manuellement les opérateurs, vous serez exposé au monde de la gestion des exceptions dans un contexte trop bas pour que RAII soit pratique, et pour obtenir des exceptions. la sécurité dans un contexte aussi peu complexe est très difficile (vous devez prétendre que n'importe quelle fonction peut lancer et saisir toutes les possibilités et annuler tous les effets secondaires comme une transaction indivisible comme si rien ne s'était passé). Le code C peut souvent "

Et il serait impossible d'implémenter de tels allocateurs dans des langages qui ne vous permettent pas d'être "dangereux" ici; vous devriez vous appuyer sur les allocateurs qu'ils fournissent (mis en œuvre probablement en C ou C ++) et espérez que cela convient à vos besoins. Et il existe presque toujours des allocateurs et des structures de données plus efficaces, mais moins généraux, adaptés à vos objectifs spécifiques mais beaucoup plus étroitement applicables car ils sont spécifiquement adaptés à vos objectifs.

La plupart des gens n'ont pas besoin de C ++ ou de C ++, car ils peuvent simplement appeler un code implémenté à l'origine en C ou C ++ ou même un assemblage déjà implémenté pour eux. Nombreux sont ceux qui pourraient tirer parti d’innovations de haut niveau, telles que l’enchaînement d’un programme d’image qui n’utilise que des bibliothèques de fonctions de traitement d’images existantes déjà implémentées en C, dans le cadre duquel elles n’innovent pas au niveau le plus bas en boucle, mais peut-être offrant une interface utilisateur très conviviale et un flux de travail jamais vu auparavant. Dans ce cas, si le but du logiciel est simplement de faire des appels de haut niveau dans des bibliothèques de bas niveau ( "traiter toute cette image pour moi, pas pour chaque pixel, faire quelque chose" ), alors ce pourrait être une optimisation prématurée d'essayer même de commencer à écrire une telle application en C.

Mais si vous faites quelque chose de nouveau au niveau bas, qui facilite l’accès aux données de bas niveau, comme un tout nouveau filtre d’image jamais vu auparavant, qui est suffisamment rapide pour fonctionner en temps réel avec la vidéo HD, vous devez généralement obtenir un peu dangereux.

Il est facile de prendre cela pour acquis. Je me souviens d'une publication sur Facebook avec une personne expliquant comment il était possible de créer un jeu vidéo 3D avec Python, ce qui impliquait que les langages de bas niveau devenaient obsolètes. Il s'agissait certainement d'un jeu décent. Mais Python effectuait des appels de haut niveau dans les bibliothèques implémentées en C pour effectuer tout le travail fastidieux. Vous ne pouvez pas créer Unreal Engine 4 en faisant simplement des appels de haut niveau dans des bibliothèques existantes. Unreal Engine 4 estla bibliothèque. Il a fait toutes sortes de choses qui n’existaient pas dans d’autres bibliothèques et moteurs, allant de l’éclairage à son système de plan directeur nodal, en passant par la compilation et l’exécution de code à la volée. Si vous souhaitez innover au niveau de bas niveau moteur / noyau / noyau, vous devez obtenir un niveau bas. Si tous les développeurs de jeux passaient dans des langages sécurisés de haut niveau, il n'y aurait ni Unreal Engine 5, ni 6, ni 7. Il s'agirait probablement de personnes utilisant encore Unreal Engine 4 décennies plus tard, car vous ne pouvez pas innover au niveau requis pour venir. avec un moteur de nouvelle génération en faisant simplement des appels de haut niveau dans l’ancien.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.