Académique Documents
Professionnel Documents
Culture Documents
Historique
1972 : Dennis Richie & Ken Thompson (Bell Labs) pour dvelopper le systme UNIX 1980 : C devient populaire plusieurs compilateurs 1983 : ANSI (American National Standards Institute) normalise le langage 1989 : fin de la normalisation qui donne la norme ANSI C
Cours C - Nazha SELMAOUI 2
TDA
Description dun type de donnes grce
La liste des oprations lies ce type Pour chaque opration :
Donnes dentre/sortie Prconditions, etc. Algorithme
Notion de modularit
Dcoupage dune application en petits modules indpendants (correspondant des TDA) Lapplication est considre comme un client qui utilise les services fournis par diffrents modules
Avantages :
Mise au point spare Rutilisabilit Evolutivit
Cours C - Nazha SELMAOUI 7
Rutilisabilit
Un mme module peut tre utilis par diffrents clients ou par dautres modules (rduction du temps de dveloppement) Aucun risque derreur si la mise au point a t faite correctement Exemples :
Dans une application universitaire, utilisation du module Liste pour grer des listes dtudiants Dans une application graphique 3D, utilisation du module Liste pour grer des listes dobjets 3D afficher Pour crire un module Pile, utilisation du module Liste avec des restrictions
Cours C - Nazha SELMAOUI 9
Evolutivit
Un module indpendant peut tre compris et amlior facilement, ventuellement par un autre dveloppeur que lauteur du module (rduction du
temps de dveloppement)
Un client peut facilement dcider de faire appel un module plutt quun autre plus performant sans modifier le code de lapplication
Cours C - Nazha SELMAOUI 10
Langage C et modularit
Le langage C nest pas un bon langage de programmation modulaire :
Utilis initialement pour la programmation systme Beaucoup de caractristiques difficiles comprendre pour les noninitis Pas de gestion automatique de la mmoire
Encapsulation
Fait de cacher au client qui utilise un module la dfinition exacte des oprations :
Pour utiliser le module, le client na besoin de connatre que la liste des oprations (fichier dentte) Il na pas connaissance des dtails de limplantation contenue dans le fichier source
15
C est un langage compil langage interprt programme C dcrit par un fichier texte appel fichier source (*.c) traduit en langage machine par un compilateur La compilation se dcompose en 4 phases:
traitement par le prprocesseur la compilation l assemblage l dition de liens
Compilation
16
Traitement par le prprocesseur : ralise des transformations d ordre purement textuel (inclusion d autres fichiers sources, etc.) (*.i) Compilation : traduit le fichier gnr par le prprocesseur en assembleur (*.s) Assemblage : transforme le code assembleur en fichier binaire appel fichier objet (*.o) Edition de liens : lie entre diffrent objet (sources de fichiers spars) pour produire un fichier excutable.
Cours C - Nazha SELMAOUI 17
Compilation (suite)
Compilation
Fichier objet M1.o Fichier objet M2.o ... Fichier objet main.o
Bibliothques externes
Excutable
Cours C - Nazha SELMAOUI 18
Avantages
Compilation indpendante de chaque module Si le code source dun module est modifi, seuls ce module et ceux qui lutilisent doivent tre recompils
19
20
Syntaxe de Makefile
Dfinition de variables :
nom = valeur
24
25
Identificateurs
Un identificateur peut dsigner :
Nom de variable ou fonction type dfini par typedef, struct, union ou enum, tiquette
Premier caractre nest jamais un chiffre minuscules et majuscules sont diffrencies longueur>=31
Cours C - Nazha SELMAOUI 26
Mots-clefs
Rservs pour le langage lui-mme et ne peuvent tre utiliss comme identificateur, 32 mots-clefs :
const, double, int, float, else, if, etc.
Commentaires
Structure d un programme C
Une expression est une suite de composants lmentaires syntaxiquement correcte, par exemple :
x=0 (i>=0) && (i<10) && (p[i] !=0)
28
Structure d un programme C
Plusieurs instructions peuvent tre rassembles par des accolades { } et forme une instruction compose ou bloc, par exemple :
if (x !=0) { z = y / x; t = y % x; }
Cours C - Nazha SELMAOUI 29
Structure d un programme C
Une instruction compose d un spcificateur de type et d une liste d identificateurs spars par une virgule est une dclaration, par exemple :
int a; int b = 1, c; char message[80];
Structure d un programme C
31
Les fonctions secondaires peuvent tre places indiffremment avant ou aprs la fonction principale :
type ma_fonction ( arguments ) { dclarations de variables internes instructions } cette fonction retourne un objet de type type, les arguments ont une syntaxe voisine des dclarations, par exemple :
int produit (int a, int b) { int resultat; resultat = a * b; return(resultat); }
Cours C - Nazha SELMAOUI 32
Structure dun programme C La fonction main peut avoir des paramtres formels
unsigned
33
int : mot naturel de la machine. Pour PC Intel = 32bits. int peut tre prcd par
un attribut de prcision : short ou long un attribut de reprsentation : unsigned
Caractre Entier court Entier Entier long char short int long 8 bits 16 bits 32 bits 32 bits
Les constantes
Valeur qui apparat littralement dans le code source, le type de constante tant dtermin par la faon dont la constante est crite. 4 types : entier, rel, caractre, chane de caractre Caractre imprimable mis entre apostrophes : 'A' ou '$'
Cours C - Nazha SELMAOUI 37
Affectation :
Les oprateurs
variable = expression expression est valu et est affecte variable. L'affectation une conversion de type implicite : la valeur de l'expression est convertit dans le type du terme gauche.
main() { int i, j = 2; float x = 2.5; i = j + x; x = x + i; printf("\n %f \n",x) }
Cours C - Nazha SELMAOUI 39
Boolens :
&& : || : ! :
Bit bit :
& | ^ ~ <<(>>) :
|=
44
Oprateur virgule
Suite d'expressions spares par une virgule expression1 , expression2 , expression 3 Expression value de gauche droite, sa valeur sera la valeur de l'expression de droite
main() { int a , b b = ((a = 3) , (a + 2)); printf("\n b= %d\n",b); } imprime b = 5
Cours C - Nazha SELMAOUI 45
Cette expression est gale expression1 si la condition est vraie et expression2 sinon
x>=0 ? x : -x; correspond la valeur absolue m = ((a>b) ? a : b); affecte m le maximum de a et b
46
Oprateur adresse
L'oprateur d'adresse & appliqu une variable retourne l'adresse-mmoire de cette valeur
&objet
48
else if (expression2)
Instruction2 ...
case constante2 :
liste d'instructions2; break; ...
default :
liste d'instructionsn; Break;
}
Cours C - Nazha SELMAOUI 50
Les boucles
while : while (expression) instruction; Tant que expression est non nulle, instruction est excute. Si expression est nulle instruction ne sera jamais excute
I=1; While (i < 10) { printf("\n i = %d",i); I++; }
Les boucles
do ---- while : do instruction; while (expression); Ici l'instruction est excute tant que expression est non nulle. Instruction est toujours excute au moins une fois.
int a; do { printf("\n Entrez un entier entre 1 et 10 : "); scanf("%d",&a); } while ((a <=0) || (a > 10))
52
Les boucles
for : for ( expr1; expr2; expr3) instruction; quivalent
expr1; while (expr2); { instruction; expr3; }
Exemple :
for (i = 0; i < 10; i++) printf("\n i = %d",i);
Cours C A la fin de la boucle i vaut 10Nazha SELMAOUI 53
56
57
58
Chane de contrle indique le format dans lequel les donnes lues sont converties, ne contient pas le caractre "\n". Mme format que printf une lgre diffrence.
#include <stdio.h> main() { int i; printf("entrez un entier sous forme hexadcimale i ="); scanf("%x",&i);) printf("i = %d\n",i); }
getchar(); retourne un int, on doit crire : caractere = getchar(); lorsqu'elle dtecte la fin du fichier elle retourne l'entier EOF valeur dfinie dans le stdio.h et vaut -1. putchar(caractere); retourne un int ou EOF en cas d'erreur.
#include <stdio.h> main() { char c; while ((c = getchar()) != EOF) putchar(c); } on peut utiliser un fichier texte.
Cours C - Nazha SELMAOUI 60
Tableaux et pointeurs en C
1. Tableaux: principe et stockage
62
19
64
66
-1
7 int tb1[10] = {
21
32
-4
21
32
-4
1
67
Tableaux et pointeurs en C
2. Adresses et pointeurs
Organisation de la mmoire
La mmoire (RAM) est un immense tableau de cases contenant chacune 1 octet (ou byte) = 8 bits
Une variable est stocke sur une ou plusieurs cases en fonction de son type et de la machine. En gnral :
Entiers courts (short int): 2 octets Entiers (int) et rels en simple prcision (float): 4 octets Rels en double prcision (double): 8 octets
Notion dadresse
Ladresse dune variable correspond au numro de la premire case stockant cette variable
Ex: entier ladresse 103 est en fait stock dans les cases 103, 104, 105 et 106 104 105 106 107 0 103
Le nombre dadresses disponibles dpend de la taille de la mmoire mesure en Go 109 octets milliards de cases
Cours C - Nazha SELMAOUI 70
Oprateur &
En langage C, ladresse en mmoire dune variable est donne par &variable Mme principe dans le cas des tableaux :
&(tb1[i]) correspond ladresse en mmoire de tb1[i]
&tb1[0] &tb1[1] &tb1[2]
tb1[0]
tb1[1]
tb1 est en fait ladresse en mmoire du premier lment du tableau, cest--dire 71 &(tb1[0]) Cours C - Nazha SELMAOUI
Exemple 1:
tb1 + 4 correspond ladresse de la 1re case laquelle on ajoute 4 adresses, cest--dire &(tb1[4])
tb1 ou tb1 + 0 &(tb1[0]) tb1 + 1 &(tb1[1]) tb1 + 2 &(tb1[2]) Cours C - Nazha SELMAOUI
72
Exemple 3 :
&(tb1[7]) &(tb1[3]) correspond au nombre dadresses entre tb1[7]) et tb1[3]) 4
73
Notion de pointeur
Un pointeur est une variable permettant de stocker une adresse-mmoire
Dclaration :
type *pointeur ; le type est celui des variables auxquelles permet daccder le pointeur
Exemples :
int *pt_int ; /* pointeur sur un entier */ char *pt_char; /* pointeur sur un caractre */
Cours C - Nazha SELMAOUI 74
Arithmtique de pointeurs
Laddition et la soustraction fonctionnent comme avec les adresses
int tb1[10], *p1, *p2 ; p1 = tb1 + 3 ; /* p1 pointe sur tb1[3] */ p2 = p1 1 ; /* p2 pointe sur tb1[2] */
76
Oprateur *
Permet daccder au contenu dune variable par un pointeur :
int x, y, *p ; x = 10 ; p = &x ; y = *p ; /* y doit contenir 10 */
Notion de pointeur
int i = 3 int *p; p = &i;
valeur 3 431836000
objet i j p1 p2
aprs l'affectation de p2 p1
objet i j p1 p2
objet adresse valeur i 431836000 3 j 431836004 6 p1 431835984 431836004 Nazha SELMAOUI4831835992 431836004 79 p2
Types volus
Types construits par lutilisateur en assemblant divers types de valeurs :
Tableaux numrations Structures Unions
81
numrations
Dfinition dun type par spcification dun ensemble de valeurs possibles Syntaxe :
enum nom_type {val1, val2, val3, } ; Ou enum nom_type {val1=entier1, val2=entier2, } ;
Ex. :
enum couleur {ROUGE, VERT, BLEU} ; Par dfaut, ROUGE est associ 0, VERT 1, enum booleen {faux = 12, vrai = 23};
Cours C - Nazha SELMAOUI 82
numrations
Combinaison avec typedef pour viter davoir crire tout le temps enum (pour allger l'criture des programmes on affecte un nouvel identificateur un type compos):
typedef type synonyme; typedef enum couleur Couleur ; Couleur c ; c = BLEU ;
Cours C - Nazha SELMAOUI 83
Allocation dynamique
Fonction malloc :
malloc (nombre_octets)
Alloue une zone de taille nombre_octets octets en
mmoire et retourne un pointeur de type char* qu'il faut concertir l'aide d'un cast. cette fonction se trouve dans la librairie standard stdlib.h L'argument nombre_octets est souvent donn l'aide de la fonction sizeof() qui renvoie le nombre d'octets utiliss pour stocker un objet. Ex : int * p; p = (int*)malloc(sizeof(int)); en principe sizeof(int)=4 Cours C - Nazha SELMAOUI 84
Allocation dynamique
Exemple :
#include<stdio.h> #include<stdlib.h> main() { int i = 3; int *p; printf("valeur de p avant initialisation = %ld\n",p); p = (int*)malloc(sizeof(int)); printf("valeur de p aprs initialisation = %ld\n",p); *p = i; printf("valeur de *p = %d\n",*p); }
Cours C - Nazha SELMAOUI
Dfinit un pointeur p sur un objet *p de type int, et affecte *p la valeur de la variable i. rsultat du programme : valeur de p avant initialisation = 0 valeur de p aprs initialisation = 5368711424 valeur de *p = 3
85
Allocation dynamique
#include<stdio.h> #include<stdlib.h> Dfinit un pointeur p sur un objet *p de type int, rserve 2 places main() d'objets de type int l'adresse p (8 octets). { rsultat du programme :
p = 5368711424 *p = 3 p+1 = 5368711428 int i = 3; int j = 6; int *p; p = (int*)malloc(2*sizeof(int)); *p = i; *(P+1) = j; printf("p = %ld \t *p = %d \t p+1 = %ld \t *(P+1) = %d \n",p,*p,p+1,*(p+1)); *(p+1) = 6
86
Allocation dynamique
La fonction calloc(nb-objets,taille-objets) joue le mme rle que malloc sauf que celle-ci initialise en plus l'objet point *p 0
Ex : p =(int*)calloc(N,sizeof(int)); p = (int*)malloc(N * sizeof(int)); for (i = 0; i < N; i++) *(p+i) = 0;
Cours C - Nazha SELMAOUI 87
Allocation dynamique
Sil ny a plus de place en mmoire, malloc retourne ladresse NULL (constante dfinie dans la bibliothque <malloc.h>)
tester systmatiquement
Pour librer une zone mmoire alloue prcdemment avec malloc, on utilise la fonction free :
free(nom_du_pointeur) ;
Cours C - Nazha SELMAOUI 88
89
91
92
imprime la valeur 0
Cours C - Nazha SELMAOUI 94
Unions
Mme fonctionnement que la structure, mais un seul emplacement mmoire est allou pour lensemble des champs
Utilise pour une donne pouvant tre de diffrents types ( des moments diffrents) union nom_type { type1 champ1 ; type2 champ2 ; }; La taille mmoire est celle du type le plus grand parmi les champs
95
Unions
Exemple :
union jour { char lettre; int numero; }; main() { union jour hier, demain; hier.lettre = 'J'; printf("hier = %c\n",hier.lettre); hier.numero = 4; demain.numero = (hier.numero + 2) % 7; printf("demain = %d\n",demain.numero); }
Cours C - Nazha SELMAOUI 96
Unions
Exemple :
union contenu { int val_entier ; float val_reel ; char val_car ; }; typedef union contenu Contenu ;
Unions - Exemple
enum typeDrapeau {ENTIER, REEL, CAR} ; typedef enum typeDrapeau TypeDrapeau ; union contenu { int val_entier ; float val_reel ; char val_car ; }; typedef union contenu Contenu ; struct element { TypeDrapeau drapeau ; Contenu val ; }; typedef struct element Element ;
Cours C - Nazha SELMAOUI 98
Unions - Exemple
Ou :
void afficher_element (Element x) { switch (x.drapeau) { case ENTIER: printf("Valeur = %d\n", x.val.val_entier) ; break; case REEL: printf("Valeur = %g\n", x.val.val_reel) ; break; case CAR: printf("Valeur = %c\n", x.val.val_car) ; break; default: printf("Donne inconnue !\n"); } } void afficher_element (Element x) { if (x.drapeau == ENTIER) printf("Valeur = %d\n", x.val.val_entier) ; else if (x.drapeau == REEL) printf("Valeur = %g\n", x.val.val_reel) ; else if (x.drapeau == CAR) printf("Valeur = %c\n", x.val.val_car) ; else printf("Donne inconnue !\n"); }
99
Structures
quivalent de lenregistrement en algorithmique Type htrogne compos de plusieurs champs pouvant avoir chacun leur propre type Syntaxe :
struct nom_type { type1 champ1 ; type2 champ2 ; type3 champ3 ; };
dclaration :
101
Structures
Ou :
struct nom_type { type1 champ1 ; type2 champ2 ; type3 champ3 ; } objet ;
102
Structures
Exemple de structure :
struct etudiant { int INE ; char nom [80], prenom [80] ; };
Initialisation la dclaration :
struct etudiant e = {70081, "Bush", "Georges"};
Cours C - Nazha SELMAOUI 103
Structures
Utilisation de typedef :
typedef struct etudiant Etudiant ; Etudiant e ;
104
#include<math.h> struct complexe{ double reelle; double imaginaire; }; main() { struct complexe z; double norme; norme=sqrt(z.reelle * z.reelle + z.imaginaire * z.imaginaire); printf("norme de (%f + i %f) = %f \n",e.reelle,z.imagianire,norme); }
Structures
105
Utilisation du symbole -> pour accder aux champs dans le cas des pointeurs :
pe->INE = 12 ; Ou (*pe).INE = 12 ;
Cours C - Nazha SELMAOUI 106
107
Structures et fonctions
Une variable de type structure peut tre passe en entre dune fonction et/ou renvoye en sortie
Mieux vaut passer par un pointeur sur la structure si cette dernire contient beaucoup de champs
Cours C - Nazha SELMAOUI 108
Structures imbriques
Imbrication dune structure dans une autre structure :
struct date { int jour, mois, annee; }; typedef struct date Date ; struct etudiant { int INE ; char nom[80], prenom[80]; Date date_naissance ; }; typedef struct etudiantCours C - Nazha SELMAOUI Etudiant ;
109
Structures imbriques
On peut toujours initialiser la dclaration :
Etudiant e = {70081, "Bush", "Georges", {12, 06, 1978} } ;
110
Structures auto-rfrentes
Utilisation dun champ qui soit du mme type que la structure :
struct etudiant { int INE ; char nom [80], prenom [80] ; struct etudiant binome ; }; INCORRECT (le compilateur ne connat pas la taille mmoire rserver pour le champ binome)
Utilisation de ladresse :
struct etudiant { int INE ; char nom [80], prenom [80] ; struct etudiant *binome ; }; Cours C - Nazha SELMAOUI
111
Adresse cell. 1
Contenu cell. 1 Adresse cell. 2
Adresse cell. 2
Contenu cell. 2 Adresse cell. 3
Adresse cell. 3
Contenu cell. 3 Adresse cell. 4
113
Chanage supplmentaire
Sur le mme principe
struct cellule { /* champs correspondants au contenu */ struct cellule *suiv ; struct cellule *prec ; }; Ou struct cellule { /* champs correspondants au contenu */ struct cellule *filsgauche ; struct cellule *filsdroit ; };
Cours C - Nazha SELMAOUI 114
Directives
Prprocesseur est un programme excut lors de la premire compilation il effectue des modifications textuelles sur le fichier source partir de directives :
incorporation de fichiers source (#include) dfinition de constantes symboliques et de macros (#define) compilation conditionnelle (#if, #ifdef, )
117
Directive #include
Permet d'incorporer dans le fichier source le texte figurant dans un autre fichier :
fichier en tte de la librairie standard (stdio.h, math.h, ) n'importe quel autre fichier
Syntaxe ,:
#include<nom-de-fichier> : fichier se trouvant dans les rpertoires systmes (ex : /usr/include/) #include "nom-de-fichier" : fichier dans le rpertoire courant
118
Directive #define
Permet de dfinir :
des constantes symboliques
#define nom reste-de-la-ligne : demande au prprocesseur de substituer toute occurrence de nom par la chane reste-de-la-ligne ex : #define NB_LIGNES 10
#define NB_COLONNES 33 #define TAILLE_MATRICE NB_LIGNES * NB_COLONNES
Directive #define
Exemple :
#define FOR for( #define WHILE while( #define DO ){ #define OD ;} #define REP do{ #define PER }while( #undef DONE #define DONE ); #define LOOP for(;;){ #define POOL } #define IF if( #define THEN ){ #define ELSE } else { #define ELIF } else if ( #define FI ;} #define BEGIN { #define END } #define SWITCH switch( #define IN ){ #define ENDSW }
120
La compilation conditionnelle
A pour but d'incorporer ou d'exclure des parties du code source dans le texte qui sera gnr par le prprocesseur Permet d'adapter le programme au matriel ou l'environnement sur lequel il s'excute, ou d'introduire dans le programme des instructions de dbogage directive en 2 catgories lie :
la valeur d'une expression l'existence ou l'inexistence de symboles
Cours C - Nazha SELMAOUI 121
La compilation conditionnelle
Condition lie la valeur d'une expression
#if codition-1
partie-du-programme-1
#elif condition-2
partie-du-programme-2
#elif condition-n
partie-du-programme-n
#else partie-du-programme- le nombre de #elif est quelconque et le #else est facultatif chaque condition-i doit tre une expression constante une seule partie-du-programme sera compile : celle qui correspond la premire condition-i non nulle
122
La compilation conditionnelle
Exemple :
#define PROCESSEUR ALPHA #if PROCESSEUR == ALPHA
taille_long = 64;
#elif PROCESSEUR == PC
taille_long = 32;
#endif
#else
partie-du-programme-2
#endif si symbole est dfini au moment o l'on rencontre la directive #ifdef, alors partie-du-programme-1 sera compile dans le cas contraire c'est
Cours C - Nazha SELMAOUI 123
La compilation conditionnelle
Exemple :
#define DEBUG ... #ifdef DEBUG
for (i = 0; i < N; i++) printf("%d\n",i);
On peut remplacer l'instruction #define DEBUG au moment de la compilation par gcc -DDEBUG fichier.c
124
Les fonctions
type dsigne le type de la fonction i.e. le type de la valeur qu'elle retourne si la fonction ne renvoie pas de valeur elle est de type void.
Cours C - Nazha SELMAOUI 126
Ex :
int produit (int a, int b) { return(a * b); } void imprime_tab (int *tab, int nb_elements) { int i; for ( i = 0; i < nb_elements, i++) printf("%d \t",tab[i]); printf("\n"); return; Cours C - Nazha SELMAOUI }
127
}
main() {
int a = 2, b = 5; printf("%d\n",puissance(a,b));
}
Cours C - Nazha SELMAOUI 129
130
131
La fonction main
La fonction principale main est une fonction comme les autres. Elle est souvent dclare sans type mais l'option -Wall de gcc provoque un message d'avertissement. En fait la fonction main est de type int dont la valeur est 0 si l'excution se passe bien diffrente de 0 sinon On peut utiliser deux constantes dfinies dans la librairie stdlib.h :
EXIT_SUCCESS = 0 EXIT_FAILURE = 1
137
La fonction main
La fonction main peut galement possder des paramtres formels. En effet un programme C peut recevoir une liste d'arguments au lancement de son excution. La ligne de commande est dans ce cas l est compose du nom du fichier excutable suivi par des paramtres. main possde 2 paramtres formels appels par convention :
argc (argument count) : variable de type int fourni le nombre de mots composant la ligne de commande y compris l'excutable. argv (argument vector) : est un tableau de chanes de caractres correspondant chacune un mot de la ligne de commande.
argv[0] contient le nom du fichier excutable argv[1] contient le premier paramtre
La fonction main
#include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[]) {
int a, b; if (argc !=3) { printf("\nErreur : nombre invalide d'arguments"); printf("\nUsage : %s int int \n",argv[1]); printf(EXIT_FAILURE); } a = atoi(argv[1]); b = atoi(argv[2]); printf("\nLe produit de %d par %d vaut : %d\n", a, b, a * b); return(EXIT_SUCCESS);
est de type
type (*)(type-1,,type-2);
Ex :
int operateur_binaire(int a, int b, int (*f)(int, int));
pour appeler la fonction oprateur en utilisant la fonction somme de prototype : int somme(int, int); on crit : operateur_binaire(a, b, somme)
Cours C - Nazha SELMAOUI 140
141
int main(int argc, char *argv[]); { int a, b; if (argc !=4) { printf("\nErreur : nombre invalide d'arguments"); usage(argv[0]); return(EXIT_FAILURE); } a = atoi(argv[1]); b = atoi(argv[1]); if (!strcmp(argv[2], "plus")); { printf("%d\n",operateur_binaire(a,b,somme)); return(EXIT_SUCCESS); } if (!strcmp(argv[2], "fois")); { printf("%d\n",operateur_binaire(a,b,produit)); return(EXIT_SUCCESS); } else { printf("\nErreur : argument(s) invalide(s)"); usage(argv[0]); return(EXIT_Failure); } Cours C - Nazha SELMAOUI 142 }
La programmation modulaire
Principes lmentaires
Ncessit de fractionner un programme C en plusieurs fichiers sources, que l'on compile sparment 3 rgles d'criture d'un programme C :
l'abstraction des constantes littrales la factorisation du code la fragmentation du code
Cours C - Nazha SELMAOUI 144
Principes lmentaires
L'abstraction des constantes littrales : viter d'utiliser explicitement des constantes littrales dans le corps, ceci rend les modifications et la maintenance difficile :
fopen("nom_fichier","r"); perimetre = 2 * 3.14 * rayon; sauf le cas particulier des constantes symboliques au moyen de la directive #define.
145
Principes lmentaires
La factorisation du code : viter de dupliquer du code. Dfinition systmatiquement des fonctions (mme de petite taille) la fragmentation du code : dcoupage d'un programme en plusieurs fichiers pour plus de lisibilit.
Placer une partie du code dans un fichier en-tte (ayant l'extension .h) que l'on inclut dans le programme principale par la directive #include.
146
Principes lmentaires
/************************************************************/ /**** fichier : main.c ****/ /**** saisit 2 entiers et affiche leur produit ****/ /************************************************************/ #include <stdio.h> #include <stdlib.h> #include "produit.h" int main(void) { int a, b , c; scanf("%d",&a); scanf("%d",&b); c = produit(a,b); printf("\nle produit vaut %d\n",c); return EXIT_FAILURE } /************************************************************/ /**** fichier : produit.h ****/ /**** produit de 2 entiers ****/ /************************************************************/ int produit (int , int) int produit (int a, int b) { return(a * b); }
147
La compilation spare
Si on reprend l'exemple prcdent, on doit compiler les fichiers sparment :
gcc -c produit.c gcc -c main.c gcc main.o produit.o Si on compile avec l'option -Wall, la compilation il y aura un message de warning qui rappelle que la fonction produit n'a pas t dclare dans le main. On peut galement faire une seule commande : gcc produit.c main.c
La compilation spare
Fichier en-tte d'un fichier source :
le fichier en-tte nom.h doit tre inclus par la directive #include dans tous les fichiers sources qui utilisent une des fonctions dfinies dans nom.c. il faut faire, par ailleurs, prcder la dclaration de la fonction du motclef extern, qui signifie que cette fonction est dfinie dans un autre fichier. Exemple :
149
La compilation spare
/**********************************/ /**** fichier : produit.h *****/ /**** en-tete de produit.c *****/ /*********************************/ extern int produit (int , int); /*********************************/ /**** fichier : produit.c *****/ /**** produit de 2 entiers *****/ /*********************************/ #include "produit.h" int produit (int a, intb) { return(a *b); } /******************************************/ /**** fichier : main.c *****/ /**** saisit de 2 entiers et affiche leur produit****/ /*****************************************/ #include<stdlib.h> #include<stdio.h> #include "produit.h" int main (void) { int a, b, c: scanf("%d",&a); scanf("%d",&b); c = produit(a,b); printf("\n le produit vaut %d\n",c); return EXIT_SUCCESS; }
150
La compilation spare
Pour viter une double inclusion de fichier en-tte, il est recommand de dfinir une constante symbolique, souvent appele NOM_H au dbut du fichier nom.h dont l'existence est prcdemment teste. Si cette constante est dfinie alors le fichier nom.h a dj t inclus.
/**********************************/ /**** fichier : produit.h *****/ /**** en-tete de produit.c *****/ /*********************************/ #ifndef PRODUIT_H #define PRODUIT_H extern int produit (int , int); #endif /* PRODUIT_H*/
Cours C - Nazha SELMAOUI 151
La compilation spare
Les rgles :
tout fichier source nom.c on associe un fichier en-tte nom.h qui dfinit son interface le fichier nom.h se compose :
dclarations des fonctions d'interface ventuelles dfinitions de constantes symboliques et de macros ventuelles directives au pr-processeur
le fichier nom.h est inclus dan nom.c et dans tous les fichiers qui font appel une fonction dfinies dans nom.c
152
L'utilitaire make
Plusieurs fichiers sources compils sparment compilation longue est fastidieuse automatisation l'aide de make d'UNIX Principe de base :
Avec make, effectuer uniquement les tapes de compilation ncessaires la cration d'un excutable. make recherche par dfaut le fichier makefile ou Makefile dans le rpertoire courant. On peut utiliser un autre fichier dans ce cas lancer la commande make avec l'option -f :
make -f nom_fichier
153
l'excutable prod dpend des 2 fichiers produit.c, main.c et l'en-tte produit.h (les commentaires sont prcds de #)
make prod
Cours C - Nazha SELMAOUI 154
On peut rajouter, si on veut tre bien organis, une cible appele clean permettant de nettoyer le rpertoire courant :
clean : rm -f prod *.o
155
Macros et abrviations
Pour simplifier l'criture d'un fichier Makefile, on peut utiliser un certain nombre de macros sous la forme :
nom_de_macro = corps de la macro
quand la commande make est excute, toutes les instructions du type $(nom_de_macro) dans le Makefile sont remplaces par le corps de la macro.
## Exemple de Makefile avec macros CC = gcc prod : produit.o main.o
$(CC) -o prod produit.o main.o