Les bases de la programmation en C
Historique
Le C a été concu en 1972 par Dennis Richie et Ken Thompson, chercheurs aux Bell Labs, afin de développer un système d’exploitation UNIX sur un DEC PDP-11. En 1978, Brian Kernighan et Dennis Richie publient la définition classique du C dans le livre The C Programming language [6]. Le C devenant de plus en plus populaire dans les années 80, plusieurs groupes mirent sur le marché des compilateurs comportant des extensions particulières. En 1983, l’ANSI (American National Standards Institute) décida de normaliser le langage; ce travail s’acheva en 1989 par la définition de la norme ANSI C. Celle-ci fut reprise telle quelle par l’ISO (International Standards Organization) en 1990. C’est ce standard, ANSI C, qui est décrit dans le présent document.
La compilation
Le C est un langage compilé (par opposition aux langages interprétés). Cela signifie qu’un programme C est décrit par un fichier texte, appelé fichier source. Ce fichier n’étant évidemment pas exécutable par le microprocesseur, il faut le traduire en langage machine. Cette opération est effectuée par un programme appelé compilateur. La compilation se décompose en fait en 4 phases successives:
1. Le traitement par le préprocesseur: le fichier source est analysé par le préprocesseur qui effectue des transformations purement textuelles (remplacement de chaˆınes de caractères, inclusion d’autres fichiers source …).
2. La compilation: la compilation proprement dite traduit le fichier généré par le préprocesseur en assembleur, c’est-`a-dire en une suite d’instructions du microprocesseur qui utilisent des mnémoniques rendant la lecture possible.
3. L’assemblage: cette opération transforme le code assembleur en un fichier binaire, c’est-`a-dire en instructions directement compréhensibles par le processeur. Généralement, la compilation et l’assemblage se font dans la foulée, sauf si l’on spécifie explicitement que l’on veut le code assembleur. Le fichier produit par l’assemblage est appelé fichier objet.
10 Chapitre 1. Les bases de la programmation en C
4. L’édition de liens: un programme est souvent séparé en plusieurs fichiers source, pour des raisons de clarté mais aussi parce qu’il fait généralement appel `a des librairies de fonctions standard déj`a écrites. Une fois chaque code source assemblé, il faut donc lier entre eux les différents fichiers objets. L’édition de liens produit alors un fichier dit exécutable.
Lesdifférentstypesdefichiersutiliséslorsdelacompilationsontdistinguésparleursuffixe. Les fichiers source sont suffixés par .c, les fichiers prétraités par le préprocesseur par .i, les fichiers assembleur par .s, et les fichiers objet par .o. Les fichiers objets correspondant aux librairies pré-compilées ont pour suffixe .a. Le compilateur C sous UNIX s’appelle cc. On utilisera de préférence le compilateur gcc du projet GNU. Ce compilateur est livré gratuitement avec sa documentation et ses sources. Par défaut, gcc active toutes les étapes de la compilation. On le lance par la commande
gcc [options] fichier.c [-llibrairies]
Par défaut, le fichier exécutable s’appelle a.out. Le nom de l’exécutable peut ˆetre modifié `a l’aide de l’option -o. Leséventuelles librairies sont déclarées par la chaˆıne -llibrairie. Dans ce cas, le système recherche le fichier liblibrairie.a dans le répertoire contenant les librairies pré-compilées (généralement /usr/lib/). Par exemple, pour lier le programme avec la librairie mathématique, on spécifie -lm. Le fichier objet correspondant est libm.a. Lorsque les librairies pré-compilées ne se trouvent pas dans le répertoire usuel, on spécifie leur chemin d’accès par l’option -L.
Les composants élémentaires du C
Un programme en langage C est constitué des six groupes de composants élémentaires suivants: – les identificateurs, – les mots-clefs, – les constantes, – les chaˆınes de caractères, – les opérateurs, – les signes de ponctuation. On peut ajouter `a ces six groupes les commentaires, qui sont enlevés par le préprocesseur.
Les identificateurs
Le rˆole d’un identificateur est de donner un nom `a une entité du programme. Plus précisément, un identificateur peut désigner: – un nom de variable ou de fonction, – un type défini par typedef, struct, union ou enum, – une étiquette. Un identificateur est une suite de caractères parmi: – les lettres (minuscules ou majuscules, mais non accentuées), – les chiffres, – le “blanc souligné” ( ). Le premier caractère d’un identificateur ne peut pasˆetre un chiffre. Par exemple, var1, tab 23 ou deb sont des identificateurs valides; par contre, 1i et i:j ne le sont pas. Il est cependant déconseillé d’utiliser comme premier caractère d’un identificateur car il est souvent employé pour définir les variables globales de l’environnement C. Les majuscules et minuscules sont différenciées. Le compilateur peut tronquer les identificateurs au-del`a d’une certaine longueur. Cette limite dépend des implémentations, mais elle est toujours supérieure `a 31 caractères. (Le standard dit que les identificateurs externes, c’est-`a-dire ceux qui sont exportés `a l’édition de lien, peuvent ˆetre tronqués `a 6 caractères, mais tous les compilateurs modernes distinguent au moins 31 caractères).
Les mots-clefs
Un certain nombre de mots, appelés mots-clefs, sont réservés pour le langage lui-meme et ne peuvent pas etre utilisés comme identificateurs. L’ANSI C compte 32 mots clefs:
auto const double float int short struct unsigned break continue else for long signed switch void case default enum goto register sizeof typedef volatile char do extern if return static union while
que l’on peut ranger en catégories
– les spécificateurs de stockage auto register static extern typedef
– les spécificateurs de type char double enum float int long short signed struct union unsigned void
– les qualificateurs de type const volatile
– les instructions de contrˆole break case continue default do else for goto if switch while
– divers return sizeof