Version sans JavaScript, en lecture seule : les ateliers, les quiz et l’exécution du code n’y sont pas. Version complète · Catalogue · Se connecter
Support de cours · chapitre 0
Introduction
Pourquoi le C, ce que veut dire « compilé » et « bas niveau », et les quelques règles d'écriture qu'on tiendra tout le semestre.
Pourquoi le C
Vous avez appris à programmer en Caml : un langage où l'on décrit ce qu'on calcule, et où la machine se charge du reste. La mémoire se réserve toute seule, se libère toute seule, et une liste est une valeur qu'on ne modifie pas.
Le C est à l'autre bout. Il a été écrit au début des années 1970, par Dennis Ritchie aux laboratoires Bell, pour réécrire le système Unix, jusque-là en assembleur. Il devait donc permettre tout ce que permet l'assembleur (lire et écrire n'importe quel octet de la mémoire, parler au matériel) tout en restant lisible et portable d'une machine à l'autre. Cinquante ans plus tard, c'est toujours le langage des noyaux de système (Linux, les BSD, le cœur de Windows et de macOS), des bibliothèques de base, de l'embarqué, et des interprètes des autres langages : l'interprète de Python est écrit en C, le moteur d'exécution d'OCaml aussi.
Apprendre le C, c'est donc surtout apprendre ce que fait la machine quand un programme tourne : où sont rangées les données, ce que coûte un appel de fonction, comment un programme lit un fichier ou en lance un autre. Ce que Caml vous cachait, le C vous le montre, et vous le confie.
Les familles de langages
Compilé ou interprété
Ces définitions sont théoriques. En pratique, presque tous les langages ont des interprètes et des compilateurs : OCaml a un interprète interactif (ocaml), un compilateur vers du code natif (ocamlopt) et un troisième vers du bytecode (ocamlc). Le bytecode est un langage intermédiaire, qui n'est celui d'aucun microprocesseur réel : il est ensuite interprété, ou compilé à la volée pendant l'exécution (just-in-time). C'est aussi ce que font Java et C#.
Le C, lui, est presque toujours compilé. C'est une propriété de ses outils plutôt que du langage, mais elle a façonné le langage : tout ce qui peut être décidé avant l'exécution l'est, et rien n'est vérifié pendant.
Bas niveau ou haut niveau
| Distance au matériel | proche | forte abstraction |
|---|---|---|
| Gestion de la mémoire | à la main | automatique |
| Sûreté | faible | forte |
| Vitesse d'écriture | lente | rapide |
| Vitesse d'exécution | rapide | plus lente |
| Exemples | assembleur, C, C++ | Java, Python, OCaml, JavaScript |
Il n'y a pas de frontière nette : c'est un axe, et les langages s'y placent plus ou moins loin. Le C est tout près de l'assembleur. On y gagne le contrôle : on sait où est chaque octet, et ce que coûte chaque ligne. On y perd la sûreté : lire la onzième case d'un tableau de dix ne provoque aucune erreur, le programme lit simplement ce qui se trouve là en mémoire.
Écrire du code qu'on peut relire
Un programme est lu bien plus souvent qu'il n'est écrit : par vous dans trois semaines, par vos coéquipiers, par celui qui le corrige. Quelques règles, qu'on tiendra dans tout le cours.
Le style
- Indenter le code, toujours de la même façon. Le compilateur s'en moque ; le lecteur, non.
- Rester cohérent : une fois une convention choisie (accolades, nommage, espaces), s'y tenir dans tout le projet.
- Rester clair : une ligne fait une chose. Le C permet d'écrire des expressions très denses ; ce n'est pas une raison pour le faire.
- Des identificateurs explicites et courts :
nb_lignesplutôt quenounombre_de_lignes_du_fichier_courant. Les noms d'une lettre sont réservés aux indices de boucle. - 80 colonnes suffisent. Une ligne plus longue se coupe, ou cache une fonction qui voudrait naître.
Les commentaires
- Même du bon code a besoin de commentaires : le code dit ce qu'il fait, le commentaire dit pourquoi, et ce que le code ne peut pas dire (ce que la fonction attend de ses arguments, qui doit libérer la mémoire qu'elle rend).
- Un commentaire faux est pire que pas de commentaire : on met à jour les commentaires avec le code.
- Le temps passé à écrire un bon commentaire n'est jamais perdu.
L'optimisation
Le C a la réputation d'être le langage de la vitesse, et la tentation est grande d'écrire du code « rapide » dès la première ligne. Deux citations à garder en tête :
Make it right before you make it fast. Make it clear before you make it faster. Keep it right when you make it faster. — P. J. Plauger, The Elements of Programming Style
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. — Donald E. Knuth, Structured Programming with go to Statements (1974)
D'abord juste, puis clair ; rapide ensuite, si c'est nécessaire, et en mesurant. Le compilateur, avec -O2, fait déjà mieux que la plupart des astuces écrites à la main.
Le plan du cours
- Compiler et exécuter : comment un fichier
.cdevient un programme, les fichiers d'en-tête,make. - Pointeurs et tableaux : les adresses, le passage par adresse, l'arithmétique des pointeurs.
- La mémoire d'un programme : zone statique, pile et tas ;
mallocetfree; la mémoire virtuelle. - Structures de données : listes, files, arbres et vecteurs, et comment organiser leur code.
- Entrées-sorties : les descripteurs de fichiers,
readetwrite, les redirections et les tubes. - Processus :
fork,waitetexec, pour lancer des programmes comme le fait un shell. - Parallélisme : plusieurs fils d'exécution qui partagent la mémoire, et comment les empêcher de se marcher dessus.