Pour un développeur Python, connaître les rudiments du fonctionnement de son interpréteur (CPython ou autre) est plus utile que de connaître le C.
En vrai, si l’on se cantonne à l’interpréteur standard (ce que je fais, personnellement) je pense qu’il est bon de connaître un peu des deux, ne serait-ce que pour pouvoir aller lire le code des modules qu’on utilise (dont une partie est écrite en C), mais je suis globalement d’accord : quitte à choisir, il vaut mieux avoir des connaissances superficielles sur le fonctionnement de l’interpréteur et se dire que le code des builtins et des modules en C, c’est "du code plus rapide, avec lequel on veut minimiser les allers-retours, et qui n’a souvent pas besoin de tenir le GIL pour tourner". À moins de vouloir écrire soi-même des extensions natives (ce qui est plutôt rare, j’imagine, mais je suis mal placé pour en juger parce que c’est un de mes gros kiffs), cela suffit largement pour avoir un niveau de maîtrise "avancé" de Python.
Je ne suis pas sûr que tu saches ce que tu as besoin de faire si tu as commencé ce thread, et ce que tu veux faire en C qui ne serait pas possible avec un autre langage est probablement invalide mais compilable en C et te provoquera des crashs au mieux reproductibles, au pire indéterministes.
Sérieusement, quand je lis que "le C n’est pas un langage bas niveau", je ne peux pas m’empêcher de penser qu’on est vraiment en train d’entrer dans des considérations sémantiques fatigantes. Soit on s’accorde sur le fait qu’il y a aujourd’hui une pléthore d’autres couches d’abstraction que la seule abstraction fournie par l’OS, qui permettent entre autres de fournir des garanties qui sont vitales dans les applications de nos jours, ou au moins de grandement limiter les risques inhérents au fait de programmer en C (auquel cas, C est à peu près aussi haut niveau que le second étage de l’Empire State Building est à haute altitude — si si, on peut se tuer si on en chute — ce qui ne manquera pas de faire marrer les gens qui ont pris deux ascenseurs l’un après l’autre pour descendre du 200ème étage), soit on continue de se focaliser sur l’interaction entre le C et le matériel au travers d’un microscope, au risque de ne juste plus du tout parler la même langue, ni vivre dans le même monde que la plupart des développeurs de notre époque.
Y’a quand même une sacrée différence d’échelle qu’on ne peut pas choisir de bêtement ignorer.
J’ai pas très bien compris tes deux alternatives, mais soit, puisqu’il est visé par ta remarque, je me permets de préciser mon propos. Il est fréquent d’entendre et de lire que le C est un langage qui « touche au matériel », permet de « comprendre le fonctionnement du matériel », qui est « proche du matériel », etc. or, ben c’est franchement faux, quoi qu’on en dise.
Je comprends bien l’argument qui est de dire que si tu le compares à beaucoup d’autres langages tu es plus proche de tes données (manipulation directe des bytes) et de ton OS, je ne le remets pas en question, je dis juste que tu n’apprendras pour ainsi dire rien du fonctionnement interne de ta machine en programmant en C.
D’une part parce que cette connaissance n’est pas nécessaire sauf cas particulier (genre connaître la notion de boutisme et de bytes de bourrage pour les communications via le réseau) et, d’autre part, parce que le C a été normalisé de telle sorte qu’il fonctionne sur une machine abstraite très éloignée des machines actuelles. Pire, connaître la machine abstraite t’éloigne du fonctionnement d’une machine moderne.
D’une part parce que cette connaissance n’est pas nécessaire sauf cas particulier (genre connaître la notion de boutisme et de bytes de bourrage pour les communications via le réseau) et, d’autre part, parce que le C a été normalisé de telle sorte qu’il fonctionne sur une machine abstraite très éloignée des machines actuelles. Pire, connaître la machine abstraite t’éloigne du fonctionnement d’une machine moderne.
Oui et non.
Disons que le C standard, si tu veux écrire une application système bateau, en effet tu n’as pas besoin de comprendre cela. Tout comme pour nombre d’applications en Python ou Java, savoir ce que fait l’interpréteur ou la machine virtuelle n’est pas nécessaire.
Mais si tu cherches à vraiment coder dans ces langages, à titre pro ou perso, dans des projets plus ambitieux qu’un pendu, connaître les sous bassement du langage et ce qu’il y a autour devient nécessaire et pertinent.
Donc en C tu devras comprendre la représentation mémoire des structures, l’ordre des octets d’une entité, comment fonctionne l’éditeur de lien et la compilation en gros. Le lien avec l’OS (car c’est un avantage énorme du C, UNIX et le C ont un lien très fort). De la même façon qu’on s’attend à un vrai développeur Java ou Python de connaître certaines choses sur les abstractions sur lesquelles ces langages ont été conçus. Pour éviter des problèmes courants. Genre en Python tu fais du multithread mais tu ne piges pas pourquoi c’est plus lent que promis car tu ignores le GIL. Ou en Java tu fais n’importe quoi en pensant que la JVM gère la mémoire à ta place mais en fait on oublie comment cela fonctionne un peu en vrai.
Je ne vois pas pourquoi un développeur C non débutant devrait ignorer ce genre de détails bas niveaux qui en font sa force mais aussi sa faiblesse. Tu me diras que dans ce cas on dépasse le cadre du débutant qui apprend pour la culture. Certes, mais bon si la culture d’un langage ça se résume à savoir comment écrire les conditions et les boucles, on est assez limité dans l’aspect culture de fait.
Le C est un langage de bas niveau. Le C++ aussi. Inutile d’aller chercher plus loin. Il y a des considérations matérielles à prendre en compte là où, dans d’autres langages comme le python ou le javascript, il y a de réelles abstractions tel qu’il est question de résoudre des problèmes d’ordre supérieur sans se préoccuper du contenu véritable de la mémoire (et les exemples peuvent être nombreux).
Je n’aime pas les appellations "bas-niveau"/"haut-niveau". Cela ne veut plus dire grand chose. Les langages vont être pus ou moins riches sur le support d’une famille de features ou d’une autre. La liste des features possibles est longue: OO, metaprog, fonctionnel, impératif, safety, typage, exceptions, dialogue avec le hardware, etc. Je vois ça comme des diagrammes de Kiviat et pas une droite orientée de hauteur d’un niveau sur laquelle on place de façon absolue et ponctuelle un langage.
Après je suis d’accord que sur ce que l’on appelle abusivement, aujourd’hui, bas-niveau, C et C++, c’est pareil. Après il ne faut pas croire que l’un est plus bas-niveau que l’autre — ce qui est un mythe récurrent.
Pour le reste, ses vertus pédagogiques et la rigueur qu’il requiert pour être correctement employé font que je trouve le langage C intéressant et incontournable pour tout informaticien qui se respecte.
Je ne suis pas d’accord pour les vertus pédagogiques du C. Aucun prof n’enseigne l’utilisation correcte du langage, chose qui implique de passer le "test de Raymond Chen": un code C qui n’a pas un if toutes les deux lignes est certainement incorrect (la reformulation est mienne, tout comme l’appellation). Je rajouterai: combien savent utiliser realloc correctement? Et plein d’autres choses.
Pour rendre digeste l’enseignement du C, une croix est nécessaire sur l’enseignement d’utilisation robuste et professionnelle du C. C’est ça qui serait potentiellement pédagogique, mais ça qui n’est jamais fait… Mais bon, je me répète…
Du coup cette rigueur n’arrive qu’au moment où l’on commence à vouloir être professionnel. Elle arrive soit imposée par le contexte par ce que nous sommes sur un bon projet avec une bonne équipe, soit parce que l’on s’est sortis les doigts du derrière pour découvrir et appliquer cette rigueur.
@Taurre OK je comprends mieux ce que tu voulais dire.
Je voudrais juste préciser à mon tour ce que j’entendais derrière l’expression "bas niveau".
C est probablement le seul langage dans lequel on est obligé de manipuler "explicitement" la mémoire (OK, à travers une abstraction, soit), et cela vient avec des tas de problématiques qu’on connait bien, mais qui sont hyper nombreuses :
l’accès à une adresse qui dépasse la taille de la mémoire qui nous a été allouée,
l’accès à un espace en mémoire qui a été modifié depuis qu’on en a récupéré le pointeur sans que l’on puisse le prévoir,
la responsabilité de rendre explicitement la mémoire qui nous a été allouée,
la responsabilité de s’assurer qu’on n’essaye de rendre cet espace qu’une fois et une seule,
l’accès à une adresse en mémoire dans un espace qui ne nous est plus alloué,
…
J’enfonce des portes ouvertes, toutes ces problématiques sont connues depuis longtemps, mais C ne nous fournit (presque) aucun mécanisme qui nous permette nous en protéger : il nous laisse la responsabilité d’y faire attention, et c’est ça que j’appelle "bas niveau d’abstraction". L’abstraction la plus basse qui m’importe, en tant qu’ingénieur logiciel, n’est pas celle du matériel (le simple fait d’avoir une adresse en mémoire représentée par un entier non-signé sur 64 bits est une abstraction, si on va par là, et le fait que cet entier ne soit même pas forcément une adresse absolue en mémoire également, et j’en suis conscient) : je la considère tout simplement comme acquise, car sans elle la charge cognitive que cela me demanderait de faire mon métier serait ingérable. Par contre, les abstractions qui m’importent et que je prends sérieusement en considération sont celles qui me permettent de ne pas avoir à me soucier constamment des points que j’ai mentionnés plus haut, au bénéfice de la logique de mon programme (le service qu’il rend).
En fait, dans mon référentiel (ou dans mon vocabulaire perso…), un langage "à bas niveau", c’est même encore pire que ça, c’est un langage dans lequel j’ai simplement la possibilité de demander explicitement un espace contigu de N octets sur le tas à mon système d’exploitation pour en faire ce que bon me semble. Cette définition inclut Rust, mais pas Go, par exemple. Le "besoin de descendre aussi bas", pour moi, c’est le besoin d’avoir le contrôle de ces détails, qui est loin d’être systématique dans mon travail quotidien.
C est probablement le seul langage dans lequel on est obligé de manipuler "explicitement" la mémoire (OK, à travers une abstraction, soit), et cela vient avec des tas de problématiques qu’on connait bien, mais qui sont hyper nombreuses
Le problème de ce raisonnement, c’est que c’est aussi partiellement vrai pour les autres langages selon le domaine d’application. Si tu fais du multimédia sur android et que tu crées tout le temps de nouveaux buffers en Java sans faire de recyclage, tu as de très fortes chances d’avoir des performances pourries. Certes en C tu as un pointeur, mais tu n’as pas besoin de savoir que malloc via mmap va t’allouer plus de mémoire pour faire moins d’appels systèmes. Le haut/bas niveau dépend plus du cas d’usage que du langage pour moi. Tu peux programmer des microcontroleurs en python avec micropython comme tu peux faire du C pour programmer une application GUI desktop.
Tu peux programmer des microcontroleurs en python avec micropython comme tu peux faire du C pour programmer une application GUI desktop.
OK, mais dans le premier cas, je sais que je vais programmer avec des contraintes techniques fortes, alors que dans le second, je sais que mes plus grosses contraintes seront certainement l’ergonomie et l’expérience utilisateur, et dans ce cas je ne veux tout simplement pas avoir à me soucier en plus de manipuler la mémoire : je n’ai a priori aucune raison valable de vouloir ce genre de contrôle dans ce contexte, et bien assez d’autres chats à fouetter (le client qui trouve ça moche, tel bouton dont le comportement n’est pas intuitif, telle information, inutile à ce moment précis dans le workflow de l’utilisateur, qui devrait être affichée ailleurs…).
À moins qu’un problème de mémoire ou de performances finisse par réellement se poser, auquel cas je le réglerai en me souciant localement de ces considérations.
Tu peux programmer des microcontroleurs en python avec micropython comme tu peux faire du C pour programmer une application GUI desktop.
OK, mais dans le premier cas, je sais que je vais programmer avec des contraintes techniques fortes, alors que dans le second, je sais que mes plus grosses contraintes seront certainement l’ergonomie et l’expérience utilisateur, et dans ce cas je ne veux tout simplement pas avoir à me soucier en plus de manipuler la mémoire : je n’ai a priori aucune raison valable de vouloir ce genre de contrôle dans ce contexte, et bien assez d’autres chats à fouetter (le client qui trouve ça moche, tel bouton dont le comportement n’est pas intuitif, telle information, inutile à ce moment précis dans le workflow de l’utilisateur, qui devrait être affichée ailleurs…).
À moins qu’un problème de mémoire ou de performances finisse par réellement se poser, auquel cas je le réglerai en me souciant localement de ces considérations.
On est d’accord, ce que tu peux aussi bien faire en C ou en python, sans avoir à gérer la mémoire (pour ce que ça veut dire) si c’est ce qui te gène. Les considérations qui vont rentrer en jeu sont plutôt comment tu fais ton déploiement, quelles plate-formes, sandboxing natif ou pas, outils disponibles et qui dans ton équipe a envie de faire quoi. Et pour le C on revient juste à la situation de «quand tu veux faire du bas niveau sur certains matériels, tu as juste un compilateur C» qui est la seule justification à peu près valide de «il n’y a pas le choix, il faut faire du C pour faire du bas niveau».
ce que tu peux aussi bien faire en C ou en python, sans avoir à gérer la mémoire (pour ce que ça veut dire) si c’est ce qui te gène
Je vois assez mal comment on peut faire du C sans avoir à se poser constamment la question de qui est responsable de quel pointeur, qui devra se charger de le libérer, et plus généralement les nombreux points que je mentionne dans mon avant-dernier post.
Je vois assez mal comment on peut faire du C sans avoir à se poser constamment la question de qui est responsable de quel pointeur, qui devra se charger de le libérer, et plus généralement les nombreux points que je mentionne dans mon avant-dernier post.
Tu ne vas pas réécrire des millions de ligne de code sous prétexte qu’un langage est mieux, ni reformer tous les gens de ta boite. Tu peux aussi aller dans l’autre sens et développer des outils d’analyse de la base de code, pour apporter à peu près le même genre de garanties.
En amateur tu fais le langage que tu as envie de faire. Si tout le monde voulait le langage parfait, tout le monde ferait du pony, or il y a encore très peu de logiciel fait avec.
Dans tous les cas, je ne vois pas de raison de faire du java, mais j’ai un avis biaisé.
Et puis encore une fois gestion mémoire ça veut tout dire et rien dire en même temps.
Mais c’est parce que tu te poses des questions qui n’ont aucun intérêt à ton niveau !
Qu’importe le langage avec lequel tu débuteras, il y a peu de chances que ce soit le seul, et ce dont tu as besoin en priorité c’est d’abord d’apprendre à programmer et d’acquérir de l’expérience.
Mais tu n’es pas obligé d’apprendre la programmation avec le même langage que celui que tu seras amené à utiliser pour tes projets.
Il te sera d’ailleurs plus facile d’appréhender le C (si tu te tournes un jour vers le C) une fois que tu auras acquis les bases avec un autre langage.
La POO en C++ n’est pas sa caractéristique principale non. C’est le RAII qui différencie ce langage de son ancêtre le C.
Je n’ai pas dit que c’était sa caractéristique principale, j’ai dit que c’était une différence majeure. Certes la POO est possible en C, mais elle est extrêmement peu utilisée. Quand tu prends un programme en C et un programme en C++, tu as 99% de chances que le premier ne soit pas objet et le deuxième oui. C’est probablement la différence qui saute le plus aux yeux. L’op ne connaît aucun des deux langages, je ne pense pas que parler de RAII soit pertinent pour lui.
(Ce que je dis là a pour but de clarifier mon propos, pas de dénigrer le tien, toute connaissance est bonne à prendre pour ma part ).
Quand à savoir si le C permet vraiment de connaître ce qui se passe sous le capot, je suis dubitatif. Quand je fais un malloc sur mon PC, en vrai je ne sais pas vraiment ce qui se passe en-dessous. J’en ai une vague idée certes, mais pas beaucoup plus précise qu’un new en Java. Suffit de regarder la page sur le noyau Linux, avec le superbe schéma qui est dedans, pour voir toutes les couches traversées.
C’est vrai. Mais c’est une première étape pour avoir une idée minimale de ce qui se passe sous le capot, avant d’éventuellement descendre plus bas. Déjà ça permet d’avoir des notions d’allocation mémoire, de heap et de pile, de table de symboles, de librairies statiques/dynamiques, etc. C’est déjà un kit de survie assez essentiel je pense de connaître ces notions, même si on ne sait pas forcément grand chose du fonctionnement exact derrière (mais c’est mieux d’en avoir une idée aussi).
EDIT : je n’ai pas relevé sur le passage d’être un noob bon à n’utiliser que des frameworks si on n’a pas fait de C. Déjà, en dehors du mépris évident, en quoi framework est-il synonyme de facilité ? En quoi avoir fait du C m’aidera à faire un site web scalable, déployé dans le cloud avec un système de traitement de messages en temps réel entre différents composants ? Exemple au hasard hein. Et pourtant j’ai commencé la programmation par le C, je devrais pas être un noob bon à utiliser des frameworks.
Ouais désolé c’était un peu trollesque cette phrase dite comme ça. C’était surtout pour contrebalancer le propos qui consiste à dire qu’apprendre le C ça ne sert à rien. Ca ne sert pas à rien. Ca apporte des connaissances qui peuvent s’avérer utiles pour comprendre des bugs, orienter la réflexion par rapport aux performances et à l’optimisation, avoir parfois plus de compréhension sur des problématiques de déploiement, ou savoir se démerder quand on n’a pas de binding pour une lib ou qu’il est mal documenté. Ca m’est arrivé récemment par ex en codant en Python de devoir redescendre dans le code C du module socket pour vérifier ce qui se passe exactement (et ainsi vérifier une hypothèse par rapport à un bug), et ça m’a bien aidé de connaître le C. Sans ça, j’aurais débogué à l’aveuglette, sans vraiment comprendre d’où vient l’erreur, dans quels cas elle se reproduit et comment boucher le trou avec une certitude de 100%.
Mais j’ai bien précisé qu’avoir ces notions ça reste une compétence secondaire par rapport à celles qui sont directement liées au domaine dans lequel on travaille.
Je ne pense pas qu’il soit possible de faire un kernel en JS…
Pourquoi ? C’est une vraie question.
C’est moins une limite du langage que de ses implémentations. A priori, aucune d’entre elles n’est conçue pour fonctionner sans lib standard, pour fonctionner en mode réel (https://fr.wikipedia.org/wiki/Mode_r%C3%A9el), etc. Mais dans l’absolu on peut très bien imaginer créer une telle implémentation, et faire un kernel avec.
En effet, à la place il t’aidera à te faire virer par ton client parce qu’au lieu de répondre à sa demande, tu lui auras fait un site qui segfaulte.
Ne pas confondre "connaître le C peut s’avérer utile, même dans un projet de site web" et "faire un site web en C".
Alors choisis n’importe quel langage et pars avec. Tu es en train d’atermoyer au lieu de juste apprendre à coder, ce qui retarde d’autant plus le moment où tu commenceras à te poser des questions vraiment utiles.
+1
Mais je rejoins @nohar sur un avis : « il ne me viendrait absolument pas à l’esprit de réaliser un projet en C en 2018 »
+1
Sauf peuuuuut-être pour une lib destinée à être portable dans un maximum de langages. Et encore.
Mais honnétement, si une personne te dit qu’il veut apprendre "Du traitement réseau, algorithmie, apprendre la gestion de la mémoire, accès directe au composant, bref..", tu vas lui dire de lire un cours de C, ou des cours de programmation réseau, d’algorithmie, d’archiecture des systèmes, et d’architecture des ordinateurs ?
C’est l’op qui a posé la question "C ou C++", avec les notions suscitées uniquement en contexte.
Les langages de programmation mainstream sont tellement proche que tu peux apprendre n’importe quel langage et réussir à lire (dans les grandes lignes, ce qui est suffisant pour comprendre les tutos) les autres langages. Les concepts de variables, de fonctions, de tests et boucles, de classes, etc. sont tellement proches, que osef un peu beaucoup du choix du premier langage.
Osef du premier langage oui. Mais ce que tu dis est un peu exagéré. Si tu ne connais que Python, comprendre un code C plein de mallocs, de casts et de pointeurs n’est pas trivial et tu peux faire des contre-sens, ou simplement être effrayé et ne pas fouiner là où tu pourrais.
Connectez-vous pour pouvoir poster un message.
Connexion
Pas encore membre ?
Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte