11.5.2 : C



Le langage C a été créé dans le cadre du développement du système d'exploitation Unix, puis a graduellement étendu son influence jusqu'à devenir aujourd'hui le standard de fait pour le développement de systèmes d'exploitation et l'interaction directe avec ceux-ci. Pour cette raison, c'est aussi le langage qui a été porté sur le plus grand nombre d'architectures matérielles, au point qu'il est quasiment impossible de trouver un CPU pour lequel il n'existe pas de compilateur C. C'est un standard de fait pour la programmation bas niveau, très largement enseigné dans ce cadre.

Du fait de ses objectifs de conception, c'est un des langages actuels qui offre le contrôle le plus fin sur la machine, avec par exemple la possibilité d'accéder à des adresses mémoires arbitraires, de contrôler finement l'organisation de ses données en RAM et l'ordonnancement des accès mémoires au niveau CPU, ou de communiquer directement avec le système d'exploitation. Malheureusement, ce grand pouvoir implique aussi une grande responsabilité, car le C simplifie aussi terriblement l'écriture de code incorrect.

Par exemple, le type de données central du langage est le pointeur, abstraction minimale d'une adresse mémoire qui joue de très nombreux rôles allant de l'émulation de tableaux (ces derniers étant très mal supportés par le langage) à la gestion d'allocation mémoire en passant par la construction de structures de données de types graphe. Comme un pointeur est un objet très flexible, un programmeur faisant face à un programme utilisant intensivement ceux-ci aura souvent le plus grand mal à déterminer leur rôle exact, et ses erreurs d'interprétation seront une source fréquente de bogues. Cette flexibilité signifie aussi qu'un compilateur aura une grande difficulté à déterminer ce qui constitue une utilisation incorrecte d'un pointeur, et ne pourra donc pas aider les programmeurs en les avertissant lorsqu'ils se livrent à des opérations douteuses.

Le C offre au programmeur des moyens d'abstraction très limités, qui ne permettent notamment pas de construire des objets au rôle mieux défini que les pointeurs, donc plus facile à utiliser. Les limitations du C, comme l'absence de support des tableaux multidimensionnels, ne peuvent donc pas être facilement contournées par une bibliothèque. Plus généralement, ce vocabulaire d'abstraction limité rend très difficile d'exprimer des concepts complexes dans une interface C ou d'écrire de grosses applications en C.

En revanche, ce minimalisme a le mérite d'avoir permis au C d'acquérir une interface binaire stable et standardisée, ce qu'il est l'un des seuls langages à fournir. Pour cette raison, et du fait de son rôle dans la programmation système, il est courant de voir des langages de programmation fournir une interface avec le C, et de voir des bibliothèques exposer une interface C même quand elles ne sont pas écrites en C.

En résumé, l'utilisation du C n'est intéressante que lorsqu'on souhaite interagir directement avec le matériel ou le système d'exploitation. Ne possédant même pas un support complet des tableaux, le langage n'a aucun intérêt particulier pour le calcul, et pour tout usage applicatif généraliste il est généralement avantageusement remplacé par des langages comme C++ ou Rust qui offrent un sur-ensemble plus expressif de ses fonctionnalités.

Le C est généralement compilé statiquement vers des binaires natifs.