1
TABLE DES MATIERES 2
I. HISTORIQUE & PRESENTATION 1. UN PEU D HISTOIRE Le C a été conçu en 1972 par Dennis Richie et Ken Thompson, chercheurs aux Bell Labs, afin de développer un système d'exploitation UNIX. En 1978, Brian Kernighan et Dennis Richie publient la définition classique du C dans le livre «The C Programming language». 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. 2. PRESENTATION DU LANGAGE C Le langage C est un langage de bas niveau dans la mesure où il permet l'accès à des données que manipulent les ordinateurs (bits, octets, adresses) et qui ne sont pas toujours disponibles dans les langages évolués tels que le Fortran, le Pascal ou ADA. Le langage C a été conçu pour l'écriture de systèmes d'exploitation. Plus de 90% du noyau du système UNIX est écrit en C. Le compilateur C lui-même est écrit en grande partie en langage C ou à partir d'outils générant du langage C. Il en est de même pour les autres outils de la chaîne de compilation : Assembleurs, éditeurs de liens, pré-processeurs. De plus, tous les utilitaires du système UNIX sont écrits en C («shell», outils). Il est cependant suffisamment général pour permettre de développer des applications variées de type scientifique, ou encore pour l'accès aux bases de données (application de gestion). Le langage C est disponible sur pratiquement toutes les plate-formes, de l'ordinateur personnel jusqu'aux gros calculateurs scientifiques, en passant par les stations de travail. De nombreux logiciels du domaine des ordinateurs personnels, tels que Microsoft Word ou Excel sous le système Windows, sont eux-aussi écrits à partir du langage C, ou de son successeur orienté objet C++. Le C est un langage impératif classique qui comporte : des types standards de base (entiers, réels, caractères), des structures de contrôle (Si...alors, séquences, boucles), des constructions de types (tableaux, unions, enregistrements), des sous-programmes (appelées fonctions). Il reflète bien le savoir-faire des années 70, et se situe dans la famille du langage Pascal. Son avantage vis-à-vis du Pascal est son plus grand pragmatisme. Il autorise clairement deux styles de programmation, le style 3
«bidouille» pour produire du code efficace et le style «génie logiciel» pour produire des programmes plus lisibles, plus sûrs et plus facilement modifiables. Bien que pouvant être considéré de bas niveau, le langage C supporte les structures de base nécessaires à la conception des applications structurées. Cette caractéristique le range dans la catégorie des langages de haut niveau. Il est aussi un des premiers langages offrant des possibilités de programmation modulaire. Un programme en C peut être constitué de plusieurs modules. Chaque module est un fichier source qui peut être compilé de manière autonome pour obtenir un fichier objet. L'ensemble des fichiers objets participant à un programme doivent être associés pour constituer un fichier exécutable. 3. 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-à-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-à-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. 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 à des librairies de fonctions standard déjà é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. Les différents types de fichiers utilisés lors de la compilation sont distingués par leur suffixe. 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. 4
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 être modifié à 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 options les plus importantes du compilateur gcc sont les suivantes : -c: supprime l'édition de liens ; produit un fichier objet. -E: n'active que le préprocesseur (le résultat est envoyé sur la sortie standard). -g: produit des informations symboliques nécessaires au débogueur. 5
-Inom-de-répertoire: spécifie le répertoire dans lequel doivent être recherchés les fichiers en-têtes à inclure (en plus du répertoire courant). -Lnom-de-répertoire: spécifie le répertoire dans lequel doivent être recherchées les librairies précompilées (en plus du répertoire usuel). -o nom-de-fichier: spécifie le nom du fichier produit. Par défaut, le exécutable fichier s'appelle a.out. -O, -O1, -O2, -O3: options d'optimisations. Sans ces options, le but du compilateur est de minimiser le coût de la compilation. En rajoutant l'une de ces options, le compilateur tente de réduire la taille du code exécutable et le temps d'exécution. Les options correspondent à différents niveaux d'optimisation : -O1 (similaire à -O) correspond à une faible optimisation, -O3 à l'optimisation maximale. -S : n'active que le préprocesseur et le compilateur ; produit un fichier assembleur. -v: imprime la liste des commandes exécutées par les différentes étapes de la compilation. -W: imprime des messages d'avertissement (warning) supplémentaires. -Wall: imprime tous les messages d'avertissement. Voici les différentes étapes de la vie d un programme écrit en langage compilé : 1. Conception du programme: Analyser l application à programmer pour mettre en évidences les types de données à manipuler et les opérations à effectuer, choisir les meilleurs algorithmes pour réaliser ces opérations, décider de la manière de présenter les résultats à l utilisateur du programme, quel langage est le mieux adapté à aux taches qui doivent être réalisées par le programme, etc... C est une étape cruciale qui peut être faite sans ordinateur sous la main... 2. Ecriture du programme: Si la première étape a été faite avec soin, il s agit uniquement de traduire les résultats de la conception en un programme écrit dans le langage de programmation choisi, ici le C. 3. Compilation: C est l étape de traduction vers le langage machine. Il vérifie si le programme est lexicalement, syntaxiquement et s sémantiquement correct. Si c est le cas, il produit le code exécutable, sinon, il signale les erreurs en les localisant le plus précisément possibles dans le texte du programme et vous renvoie donc à l étape 2. 4. Exécution: Le code exécutable produit à l issu de la compilation peut être lancé, c est-à-dire soumis au système d exploitation pour être exécuté. Tant que le texte du programme n est pas modifié, il n est pas nécessaire de recompiler avant de lancer l exécutable. Il se peut que l exécution d enclenche des erreurs non détectées par le compilateur. 6
Notez bien qu un programme qui compile sans erreurs n est pas forcement correct : il se peut qu il ne satisfasse pas le cahier des charges de l application à programmer... on retourne dans ce cas à l étape 1 ou 2... II. LES BASES LA STRUCTURE D UN PROGRAMME Un programme simple se compose de plusieurs parties : des directives de précompilation une ou plusieurs fonctions dont l une s appelle obligatoirement main(), celle-ci constitue le programme principal et comporte 2 parties : la déclaration de toutes les variables et fonctions utilisées des instructions Les commentaires débutent par /* et finissent par */, ils peuvent s étendre sur plusieurs lignes. LES DIRECTIVES DE PRECOMPILATION Elles commencent toutes par un #. commande #include<stdio.h> #include<math.h> #define PI 3.14159 #undef PI Signification permet d utiliser les fonctions printf() et scanf() permet d utiliser les fonctions mathématiques définit la constante PI à partir de cet endroit, la constante PI n est plus définie Parmi ces directives, une seule est obligatoire pour le bon fonctionnement d un programme : #include <stdio.h>. En effet, sans elle, on ne peut pas utiliser les fonctions utiles pour l affichage à l écran : printf() et la lecture des données au clavier : scanf(). Nous verrons le fonctionnement de ces fonctions plus tard. LA FONCTION main() Elle commence par une accolade ouvrante {et se termine par une accolade fermante}. À l intérieur, chaque instruction se termine par un point-virgule. Toute variable doit être déclarée. main() { 7
int i ; /* declaration des variables */ instruction_1 ; instruction_2 ;... } Exemple de programme simple : III. VARIABLES & CONSTANTES 1. LES CONSTANTES Une constante est une valeur qui apparaît littéralement dans le code source d un programme, le type de la constante étant déterminé par la façon dont la constante est écrite. Les constantes peuvent être de 4 types : entier, flottant (nombre réel), caractère, énumération. Ces constantes vont être utilisées, par exemple, pour initialiser une variable. Constantes entières 1,2,3,... Constantes caractères a, A,... Constantes chaînes de caractères "Bonjour" Pas de constantes logiques Pour faire des tests, on utilise un entier. 0 est équivalent a faux et tout qui est différent de 0 est vrai. LES VARIABLES NOMS DES VARIABLES Le C fait la différence entres les MAJUSCULES et les minuscules. Donc pour éviter les confusions, on écrit les noms des variables en minuscule et on réserve les majuscules pour les constantes symboliques définies par un #define. Les noms doivent commencer par une lettre et ne contenir aucun blanc. Le seul caractère spécial admis est le soulignement (_). Il existe un certain nombre de noms réservés (while, if, case,...), dont on ne doit pas se servir pour nommer les variables. De plus, on ne doit pas utiliser les noms des fonctions pour des variables. 8
DECLARATION DES VARIABLES Pour déclarer une variable, on fait précéder son nom par son type. Il existe 6 types de variables : On peut faire précéder chaque type par le préfixe unsigned, ce qui force les variables à prendre des valeurs uniquement positives. Exemples de déclarations : Il n y a pas de type complexe. LES OPERATEURS L AFFECTATION : En C, l affectation est un opérateur à part entière. Elle est symbolisée par le signe =. Sa syntaxe est la suivante variable = expression 9
Le terme de gauche de l affectation peut être une variable simple, un élément de tableau mais pas une constante. Cette expression a pour effet d évaluer expression et d affecter la valeur obtenue à variable. De plus, cette expression possède une valeur, qui est celle expression. Ainsi, l expression i = 5 vaut 5. L affectation effectue une conversion de type implicite : la valeur de l expression (terme de droite) est convertie dans le type du terme de gauche. Par exemple, le programme suivant imprime pour x la valeur 6.500000 (et non 7), car dans l instruction i = j + x, l expression j + x a été convertie en entier. LES OPERATEURS ARITHMETIQUES Les opérateurs arithmétiques classiques sont l opérateur unaire - (changement de signe) ainsi que les opérateurs binaires. symbol Signification e + Addition - Soustraction x multiplication / Division % reste de la division (modulo) Ces opérateurs agissent de la façon attendue sur les entiers comme sur les flottants. Leurs seules spécificités sont les suivantes : Contrairement à d autres langages, le C ne dispose que de la notation / pour désigner à la fois la division entière et la division entre flottants. Si les deux opérandes sont de type entier, l opérateur / produira une division entière (quotient de la division). Par contre, il délivrera une valeur flottante dès que l un des opérandes est un flottant. Par exemple : float x; 10
x = 3 / 2; Affecte à x la valeur 1. Par contre x = 3 / 2; affecte à x la valeur 1.5 L opérateur % ne s applique qu à des opérandes de type entier. Si l un des deux opérandes est négatif, le signe du reste dépend de l implémentation, mais il est en général le même que celui du dividende. Notons enfin qu il n y a pas en C d opérateur effectuant l élévation à la puissance. De façon générale, il faut utiliser la fonction pow(x,y) de la librairie math.h pour calculer x y LES OPERATEURS RELATIONNELS o Leur syntaxe est : symbole Signification > supérieur >= supérieur ou égal < strictement inférieur <= inférieur ou égal == égal!= différent Expression1 opérateur Expression2 Les deux expressions sont évaluées puis comparées. La valeur rendue est de type int (il n'y a pas de type booléen en C ); elle vaut 1 si la condition est vraie, et 0 sinon. ATTENTION! Ne pas confondre l opérateur d affectation = et l opérateur de comparaison == LES OPERATEURS LOGIQUES && et logique ou logique! négation logique Comme pour les opérateurs de comparaison, la valeur retournée par ces opérateurs est un int qui vaut 1 si la condition est vraie et 0 sinon. o Dans une expression de type Expression1 opérateur1 Expression2 opérateur2... Expression N o L évaluation se fait de gauche à droite et s arrête dès que le résultat final est déterminé. Par exemple dans : int i; int p[10]; if ((i >= 0) && (i <= 9) &&!(p[i] == 0)) 11