Vous êtes sur la page 1sur 156

Langage C

Licence Informatique 3me anne


Nazha SELMAOUI

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

Programmation modulaire et compilation spare


1. Retour sur les Types de Donnes Abstraits

Cours C - Nazha SELMAOUI

TDA
Description dun type de donnes grce
La liste des oprations lies ce type Pour chaque opration :
Donnes dentre/sortie Prconditions, etc. Algorithme

Exemple: type de donnes Liste


Cours C - Nazha SELMAOUI 4

Implantation dun TDA


Implantation ou implmentation : traduction dun TDA donn sous forme algorithmique dans un langage de programmation En langage C, on implantera un TDA sous forme de module dans lequel chaque opration est traduite par une fonction
Cours C - Nazha SELMAOUI 5

Programmation modulaire et compilation spare


2. Programmation modulaire

Cours C - Nazha SELMAOUI

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

Mise au point spare


Les modules sont crits et tests indpendamment les uns des autres Avantage : identification plus rapide des erreurs ventuelles (rduction du temps de dveloppement)

Cours C - Nazha SELMAOUI

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

Le langage C nest pas un mauvais langage de programmation modulaire :


Syntaxe claire reprise par de nombreux langages Moyennant quelques restrictions, possibilit dcrire des modules facilement rutilisables Bonne introductionCours C - Nazha SELMAOUI la programmation objet (C++) 11

Dfinition dun module en C


Les oprations dfinissant un TDA vont tre traduites sous forme de fonctions Un module est dfini par deux fichiers :
Le fichier dentte ou dinterface (module.h) contient la liste des oprations implantes par le module Le fichier source (module.c) contient la dfinition de ces oprations

Intrt de cette approche : lencapsulation


Cours C - Nazha SELMAOUI 12

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

Exemple : bibliothque graphique Avantages :


Conceptuel : rduit le risque derreurs conomique : permet de protger le code source
Cours C - Nazha SELMAOUI 13

Processus de mise au point dune application


Mise au point de chaque module :
criture du code Compilation Test

Si un module M1 utilise un module M2 : (niveaux dinterdpendance croissants)


Mise au point de M2 Inclusion de M2 dans M1 Mise au point de M1

Mise au point de lapplication principale (fichier main.c)


Cours C - Nazha SELMAOUI 14

Programmation modulaire et compilation spare


2. Rappels sur le langage C

Cours C - Nazha SELMAOUI

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

Cours C - Nazha SELMAOUI

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)

Principe de la compilation spare


Module M1 (M1.h et M1.c) Module M2 (M2.h et M2.c) ... Fichier main.c

Compilation
Fichier objet M1.o Fichier objet M2.o ... Fichier objet main.o

dition des liens

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

Cours C - Nazha SELMAOUI

19

Programmation modulaire et compilation spare


5. Compilation spare sous UNIX

Cours C - Nazha SELMAOUI

20

Spcification des dpendances entre diffrents modules


Commande : gcc [options] fichier.c [-l librairies] Spcification dans un fichier appel Makefile (permet de gnrer ensuite lexcutable grce la commande make) Permet de spcifier galement :
Le nom du fichier excutable Le logiciel utilis pour la compilation : gcc, cc, CC, g++,
Cours C - Nazha SELMAOUI 21

Syntaxe de Makefile
Dfinition de variables :
nom = valeur

Pour utiliser une variable :


$(nom)

Exemple (spcification dun rpertoire) :


prefix = /usr/local bindir = $(prefix)/bin
Cours C - Nazha SELMAOUI 22

Syntaxe de Makefile (suite)


Rgle : suite de lignes spcifiant comment gnrer une cible : cible: dependances commande Commande : commande UNIX permettant de gnrer la cible Dpendances : ensemble de fichiers (si lun de ces fichiers a t modifi, alors la cible doit tre regnre)
Cours C - Nazha SELMAOUI 23

Makefile du module Boolen


Fichier Makefile associ au module

Cours C - Nazha SELMAOUI

24

Un programme en C est constitu de 6 composantes lmentaires :


identificateurs mots-clefs constantes chanes de caractres oprateurs signes de ponctuation + les commentaires
Cours C - Nazha SELMAOUI

Les composantes lmentaires du C

25

Identificateurs
Un identificateur peut dsigner :
Nom de variable ou fonction type dfini par typedef, struct, union ou enum, tiquette

un identificateur est une suite de caractres :


lettres, chiffres, blanc soulign (_)

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.

Dbute par /* et se termine par */


/* Ceci est un commentaire */
Cours C - Nazha SELMAOUI 27

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)

Une instruction est une expression suivie d un point-virgule (fin de linstruction)

Cours C - Nazha SELMAOUI

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];

Toute variable doit faire une dclaration avant d tre utilise en C.


Cours C - Nazha SELMAOUI 30

Un programme C se prsente de la faon suivante :


[ directives au prprocesseur ] [ dclarations de variables externes ] [ fonctions secondaires ] main () { dclarations de variables internes instructions } Cours C - Nazha SELMAOUI

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

Les types prdfinis


C est un langage typ : toute variable, constante ou fonction est d un type prcis. Les types de bases de C :
char int float double short long

unsigned
33

Cours C - Nazha SELMAOUI

Les types prdfinis


Type caractre cod sur 7 ou 8 bits:
particularit du type caractre en C est qu il est assimil un entier on peut utiliser des expressions tel que c +1 qui signifie le caractre suivant dans le code ASCII (voir table)
main() { char c = A; printf("%c", c+1); }
Cours C - Nazha SELMAOUI 34

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 types entiers

Librairies standard limits.h


Cours C - Nazha SELMAOUI 35

Les types folttants


Les types float, double et long double reprsentent les nombres en virgule flottante :
Flottant Flottant double prcision Flottant quadruple prcision float double long double 32 bits 64 bits 128 bits

Reprsentation normalise : signe,mantisse 2exposant


Cours C - Nazha SELMAOUI 36

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

Les constantes caractres (suite)


Exception des caractres imprimables \, ', ? et " sont dsigns par \\, \', \? et \". Caractres non-imprimables peuvent tre dsigns par '\code-octal' ou '\xcode-hexa', par exmple : '\33' ou '\x1b' dsigne le caractre 'espace'.
\n \t \v \b nouvelle ligne \r retour chariot tabulation horizontale \f saut de page tabulation verticale \a signal d'alerte retour arrire
Cours C - Nazha SELMAOUI 38

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

Les oprations arithmtiques


Oprateur unaire et oprateurs binaires : +, -, *, /, % (reste de la division = modulo) Contrairement au langage pascal : la division entire est dsigne par /. Si les 2 oprandes sont de types entier, / produira une division entire. Par exemple :
float x; x = 3 / 2; affecte x la valeur 1. x = 3 / 2.; affect x la valeur 1.5

pow(x,y) : fonction de la librairie math.h pour calculer xy.


Cours C - Nazha SELMAOUI 40

Les oprateurs relationnels


La syntaxe est expression1 op expression2
> >= < <= == != strictement suprieur, suprieur ou gal, strictement infrieur, infrieur ou gal, gal, diffrent

La valeur boolenne rendu est de type int


1 pour vraie 0 sinon
Cours C - Nazha SELMAOUI 41

Boolens :
&& : || : ! :

Les oprateurs logiques


et logique ou logique ngation logique : et logique : ou inclusif : ou exclusif : complment 1 dcalage gauche ( droite)
Cours C - Nazha SELMAOUI 42

Bit bit :
& | ^ ~ <<(>>) :

Oprateurs d'affectation compose


+= -= *= /= &= ^= <<= <<= Pour tout oprateur op :
expression1 op= expression2 quivaut expression1 = expression1 op expression2

|=

expression1 n'est valu qu'une seule fois


Cours C - Nazha SELMAOUI 43

Oprateurs incrmentation ou dcrementation


Incrmentation : ++ Dcrmentation : - En suffixe i++ ou en prfixe ++i : dans les deux cas la valeur de i sera incrmente, sauf pour le premier cas la valeur affecte est l'ancienne, exemple :
int a = 3, b, c; b = ++a /* a et b valent 4*/ c = b++ /* c vaut 4 et b vaut 5 */

Cours C - Nazha SELMAOUI

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

Oprateur conditionnel ternaire


Oprateur conditionnel : ?
condition ? expression1 : expression2

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

Cours C - Nazha SELMAOUI

46

Oprateur de conversion de type


Oprateur de conversion de type, appel cast, permet de modifier explicitement le type d'un objet :
(type) objet
main() { int i = 3 , j = 2; printf("%f \n", (float) i/j); } Renvoie la valeur 1.5
Cours C - Nazha SELMAOUI 47

Oprateur adresse
L'oprateur d'adresse & appliqu une variable retourne l'adresse-mmoire de cette valeur
&objet

Cours C - Nazha SELMAOUI

48

Instructions de branchement conditionnel


if ----- else
if (expression1)
Instruction1

else if (expression2)
Instruction2 ...

Le else est facultatif


If (expression)
instruction
Cours C - Nazha SELMAOUI 49

Instructions de branchement conditionnel


Switch
switch (expression)
{ case constante1 : liste d'instructions1;
break;

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++; }

Affiche les entiers de 1 9


Cours C - Nazha SELMAOUI 51

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))

saisie au clavier un entier entre 1 10

Cours C - Nazha SELMAOUI

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

Instructions de branchement non conditionnel


break : vu en switch, en gnral permet d'interrompre le droulement d'une boucle, et passe la premire instruction qui suit la boucle.
main() { int i; for (i = 0; i < 6; i++) { printf("i = %d\n ",i); if (i==3) break; } printf("valeur de i a la sortie de la boucle = %d\n,i); }
imprime i= 0 jusqu' i=3 et ensuite Cours valeur de i a la sortie de la boucle = 3 C Nazha SELMAOUI 54

Instructions de branchement non conditionnel


continue : permet de passer directement de la boucle suivante sans excuter les autres instructions de la boucle.
main() { int i; for (i = 0; i < 5; i++) { if (i==3) continue; printf("i = %d\n",i); } printf("valeur de i a la sortie de la boucle = %d\n,i); }
imprime i= 0, i=2 et i = 4 valeur de i la sortie de la boucle = 5
Cours C - Nazha SELMAOUI 55

Les fonctions d'entres/sorties classiques


Fonctions de la librairie standard stdio.h : clavier et cran, appel par la directive
#include<stdio.h> Cette directive n'est pas ncessaire pour printf et scanf.

Fonction d'criture printf permet une impression formate:


printf("chane de contrle", expr1, ..., exprn); Chane de contrle spcifie le texte afficher et les formats correspondant chaque expression de la liste. Les formats sont introduites par % suivi d'un caractre dsignant le format d'impression.

Cours C - Nazha SELMAOUI

56

Les fonctions d'entres/sorties classiques


format conversion en criture
%d %ld %u %lu %o %lo %x %lx %f %lf %e %le %g %lg %c %s int long int unsigned int unsigned long int unsigned int unsigned long int unsigned int unsigned long int double long double double long double double long double unsigned char char* dcimale signe dcimale signe dcimale non signe dcimale non signe octale non signe octale non signe hexadcimale non signe hexadcimale non signe dcimale virgule fixe dcimale virgule fixe dcimale notation exponentielle dcimale notation exponentielle dcimale, reprsentation la plus courte parmi %f et %e dcimale, reprsentation la plus courte parmi %lf et %le caractre chane de caractres

Cours C - Nazha SELMAOUI

57

Les fonctions d'entres/sorties classiques


En plus entre le % et le caractre de format, on peut ventuellement prciser certains paramtres du format d'impression:
%10d : au moins 10 caractres rservs pour imprimer l'entier %10.2f : on rserve 12 caractres (incluant le .) pour imprimer le flottant avec 2 chiffres aprs la virgule. %30.4s : on rserve 30 caractres pour imprimer la chane de caractres, mais que 4 seulement seront imprims suivis de 26 blancs

Cours C - Nazha SELMAOUI

58

Les fonctions d'entres/sorties classiques


Fonction de saisie scanf : permet de saisir des donnes au clavier.
scanf("chane de contrle",arg1,arg2,...,argn);

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); }

Si la valeur 1a est saisie alors le programme affiche i = 26


Cours C - Nazha SELMAOUI 59

Les fonctions d'entres/sorties classiques


Impression et lecture de caractres :
getchar() et putchar() : fonctions d'entres/sorties non formates

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

Dclaration dun tableau


Dclaration dun tableau de taille n :
type nom_tableau [n] ; rservation de n cases contigus en mmoire

ex. : dclaration dun tableau dentiers de taille 10 appel tb1 :


int tb1[10] ;
0 1 2 3 4 5 6 7 8 9

Cours C - Nazha SELMAOUI

62

Accs aux lments dun tableau


Modification du contenu dun lment :
ex. : 0 ?
1 tb1[3] = 19 ; 2 3 4 5 6 7 8 9

19

Pour remplir tout le tableau : modification lment par lment

Utilisation de la valeur dun lment :


ex. : x = tb1[3] + 1 ; Pour afficher tout le contenu du tableau : affichage lment Nazha SELMAOUI par lment Cours C 63

Affichage dun tableau X de rels de taille n


void affTableau (float X[ ], int n) { int i ; for (i = 0 ; i < n ; i++) printf (" Contenu de la case %d : %g", i, X[i]) ; }

Cours C - Nazha SELMAOUI

64

Mise zro des lments dun tableau X de rels de taille n


void razTableau (float X[ ], int n) { int i ; for (i = 0 ; i < n ; i++) X[i] = 0 ; }
Attention : passage par adresse dans le cas des tableaux
Cours C - Nazha SELMAOUI 65

void main () { float montableau [100] ;

razTableau (montableau, 100) ; affTableau (montableau, 100) ;


} Affiche le rsultat suivant : Contenu de la case 0 : 0 Contenu de la case 1 : 0 Contenu de la case 2 : 0 La modification dans la procdure razTableau est visible dans la procdure principale

Cours C - Nazha SELMAOUI

66

Initialisation au moment de la dclaration


Ex.: int tb1[10]1= { 21, 32, -4, 1, 37, 88, 9,5-1, 0, 6 ; 7} 0 2 3 4
21 32 -4 1 37 88 9
7 8 9

-1

7 int tb1[10] = {

Initialisation dune partie du tableau :


21, 32, -4, 1} ;
0 1 2 3 4 5 6 7 8 9

21

32

-4

Initialisation sans spcifier la taille : int tb1[ ] = { 21, 32, -4,


1} ;
0 1 2 3

21

32

-4

1
67

Cours C - Nazha SELMAOUI

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

Intervalle de valeurs possibles plus ou moins grand


Cours C - Nazha SELMAOUI 69

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

Arithmtique dadresses dans les tableaux


Les adresses-mmoire du tableau sont contigus et toutes les valeurs sont stockes sur le mme nombre de cases
on peut utiliser les oprations arithmtiques + et

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

Arithmtique dadresses dans les tableaux (suite)


Exemple 2 :
&(tb1[5]) 2 correspond ladresse de tb1[5] laquelle on soustrait 2 adresses &(tb1[3])

Exemple 3 :
&(tb1[7]) &(tb1[3]) correspond au nombre dadresses entre tb1[7]) et tb1[3]) 4

Cours C - Nazha SELMAOUI

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

Affectation dun pointeur


Affectation de ladresse dune variable :
int x, *px ; px = &x ;

Affectation de ladresse dun tableau :


int tb1[10], *p ; p = tb1; /* p pointe sur la premire case de tb1 */ ou p = &(tb1[0]) ;
Cours C - Nazha SELMAOUI 75

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] */

Cours C - Nazha SELMAOUI

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 */

Fonctionne aussi avec les adresses :


*(tab + 3) est quivalent tab[3] Cours C - Nazha SELMAOUI
77

Notion de pointeur
int i = 3 int *p; p = &i;

objet adresse i 431836000 p 431836004

valeur 3 431836000

Toute modification de *p modifie i.


Cours C - Nazha SELMAOUI 78

main() { int i = 3, j = 6; int *p1, *p2; p1 = &i; p2 = &j; *p1 = *p2; }

Notion de pointeur main()


avant la dernire ligne des deux programmes

objet i j p1 p2

adresse valeur 431836000 3 431836004 6 431835984 431836000 4831835992 431836004

{ int i = 3, j = 6; int *p1, *p2; p1 = &i; p2 = &j; p1 = p2; }

aprs l'affectation de *p2 *p1

aprs l'affectation de p2 p1

objet i j p1 p2

adresse valeur 431836000 6 431836004 6 431835984 431836000 Cours 4831835992 431836004 C -

objet adresse valeur i 431836000 3 j 431836004 6 p1 431835984 431836004 Nazha SELMAOUI4831835992 431836004 79 p2

Types volus, chanage et allocation dynamique


1. numrations et allocation dynamique

Types volus
Types construits par lutilisateur en assemblant divers types de valeurs :
Tableaux numrations Structures Unions

Cours C - Nazha SELMAOUI

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, } ;

Dfinition en dehors de toute fonction

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

Exemple de variable de type numr :


enum couleur c ; c = BLEU ;

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

Cours C - Nazha SELMAOUI

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

Pointeurs et tableaux plusieurs dimensions


Il s'agit de dfinir un pointeur de pointeur int tab[M][N];
tab pointe vers le premier lment du tableau sa valeur est &tab[0][0] tab[i], pour i entre 0 et M-1, pointe vers le premier lment de la ligne d'indice i; tab[i] a la valeur &tab[i][0]

type **nom-du-pointeur; type ***nom-du-pointeur; quivaut un tableau 3 dimensions

Cours C - Nazha SELMAOUI

89

Pointeurs et tableaux plusieurs dimensions


main() { int k, n; int **tab; tab = (int**)malloc(k * sizeof(int*)); for (i = 0; i < k; i++) tab[i] = (int*)malloc(n * sizeof(in)); for ( i = 0; i < k;i++) free(tab[i]); free(tab); }
Cours C - Nazha SELMAOUI 90

Pointeurs et chanes de caractres


Vu : chane de caractres est un tableau de caractres termin par \0 On peut dfinir un pointeur sur un objet de type char char *chaine; Affectation comme : chaine = "ceci est un texte"; Et toute autres oprations valide sur les pointeurs.

Cours C - Nazha SELMAOUI

91

Pointeurs et chanes de caractres


#include<stdio.h> main() { int i; char *chaine; chaine = "chaine de caracteres"; for (i = 0; i < *chaine !='\0'; i++) chaine++; printf("nombre de caracteres = %d\n",i); } quivaut strlen(chaine) de la librairie standard string.h.

Cours C - Nazha SELMAOUI

92

Pointeurs et chanes de caractres


Avec les pointeurs de caractres on peut concatner deux chanes.
#include<stdio.h> #include<stdlib.h> #include<string.h> main() { int i; char *chaine1, chaine2, *res, *p; chaine1 = "chaine "; chaine2 = "de caracteres"; res = (char*)malloc((strlen(chaine1) + strlen(chaine2)) * sizeof(char)); p =res; for (i = 0; i < strlen(chaine1); i++) *p++ = chaine1[i]; for (i = 0; i < strlen(chaine2); i++) *p++ = chaine2[i]; printf("%s\n",res); }
Cours C - Nazha SELMAOUI 93

Pointeurs et chanes de caractres


#include<stdio.h> #include<stdlib.h> #include<string.h> main() { int i; char *chaine1, chaine2, *res, *p; chaine1 = "chaine "; chaine2 = "de caracteres"; res = (char*)malloc((strlen(chaine1) + strlen(chaine2)) * sizeof(char)); p =res; for (i = 0; i < strlen(chaine1); i++) *res++ = chaine1[i]; for (i = 0; i < strlen(chaine2); i++) *res++ = chaine2[i]; printf("%s\n",res); }

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

Cours C - Nazha SELMAOUI

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 ;

Seul le premier champ peut tre initialis au moment de la dclaration :


Contenu x = {10.5} ; /* Affecte la valeur 10 au champ x.val_entier */
Cours C - Nazha SELMAOUI 97

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"); }

Cours C - Nazha SELMAOUI

99

Types volus, chanage et allocation dynamique


2. Structures et chanage

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 :

struct nom_type objet;

La taille rserve en mmoire est la somme des tailles des champs

Cours C - Nazha SELMAOUI

101

Structures
Ou :
struct nom_type { type1 champ1 ; type2 champ2 ; type3 champ3 ; } objet ;

Accs diffrents membres :


objet.champi le ime membre de l'objet

Cours C - Nazha SELMAOUI

102

Structures
Exemple de structure :
struct etudiant { int INE ; char nom [80], prenom [80] ; };

Exemple de dclarations de variables :


struct etudiant e ; struct etudiant tabEtudiants [100] ; /* tableau de structures */

Initialisation la dclaration :
struct etudiant e = {70081, "Bush", "Georges"};
Cours C - Nazha SELMAOUI 103

Structures
Utilisation de typedef :
typedef struct etudiant Etudiant ; Etudiant e ;

Accs aux champs : utilisation du symbole .


printf("Ltudiant %s %s a le numro %d\n", e.prenom, e.nom, e.INE) ; e.INE = 12 ;

Affectation possible entre deux variables de mme type :


Etudiant e1, e2 ; e1 = e2 ;

Cours C - Nazha SELMAOUI

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

Cours C - Nazha SELMAOUI

105

Pointeurs sur des structures


Comme pour les types de base, on peut utiliser des pointeurs sur structure :
Etudiant e, *pe ; pe = &e ; pe contiendra ladresse du premier champ de la structure

Utilisation du symbole -> pour accder aux champs dans le cas des pointeurs :
pe->INE = 12 ; Ou (*pe).INE = 12 ;
Cours C - Nazha SELMAOUI 106

Pointeurs sur des structures


#include<stdlib.h> #include<stdio.h> struct eleve{ char nom[20]; int date; }; typedef struct eleve *classe; main() { int n, i; classe tab; printf("nombre d'eleves de la classe = "); scanf("%d",&n); tab = (classe)malloc(n * sizeof(struct eleve)); for (i = 0 ; i < n; i++) { printf("\n saisie de l'eleve numero %d\n",i); printf("nom de l'eleve = "); scanf("%s",&tab[i].nom); printf("\n date de naissance JJMMAA = "); scanf("%d",&tab[i].date); } printf("\n Entrez un numero "); scanf("%d",&i); printf("\n Eleve numero %d : ",i); printf("\n nom =%s",tab[i].nom); printf("\n date de naissance = %d\n",tab[i].date); free(tab); } #include<stdlib.h> #include<stdio.h> struct eleve{ char nom[20]; int date; }; typedef struct eleve *classe; main() { int n, i; classe tab; printf("nombre d'eleves de la classe = "); scanf("%d",&n); tab = (classe)malloc(n * sizeof(struct eleve)); for (i = 0 ; i < n; i++) { printf("\n saisie de l'eleve numero %d\n",i); printf("nom de l'eleve = "); scanf("%s",&tab[i].nom); printf("\n date de naissance JJMMAA = "); scanf("%d",&tab[i].date); } printf("\n Entrez un numero "); scanf("%d",&i); printf("\n Eleve numero %d : ",i); printf("\n nom =%s",(tab +i)->nom); printf("\n date de naissance = %d\n",(tab + i)->date); free(tab); }

Cours C - Nazha SELMAOUI

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} } ;

Pour laccs aux champs, double indirection :


printf("Ltudiant %s est n le %d / %d / %d\n", e.nom, e.date_naissance.jour, e.date_naissance.mois, e.date_naissance.annee) ;

Cours C - Nazha SELMAOUI

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

Chanage par structures autorfrentes


Principe utilis pour les listes chanes :
struct cellule { /* champs correspondants au contenu */ struct cellule *suiv ; };

La tte de la liste est un pointeur sur la premire cellule


Cours C - Nazha SELMAOUI 112

Schma du chanage obtenu


Liste
Adresse cell. 1

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

La dernire cellule de la liste pointe sur ladresse NULL En mmoire :


Adresse cell. 3 Adresse cell. 1 Liste Adresse cell. 2 Contenu cell. Adresse cell. 4 3 Contenu cell. Adresse cell. 2 1 Adresse cell. 1 Contenu cell. Adresse cell. 3 2

Cours C - Nazha SELMAOUI

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

Chanage et allocation dynamique


On ne sait pas a priori combien de cellules vont constituer la liste
impossible de rserver lespace mmoire ncessaire au dbut du programme (comme avec la reprsentation par tableaux allocation statique) il faut rserver lespace ncessaire pendant lexcution : chaque fois que lon ajoute une nouvelle cellule, on alloue lespace pour cette cellule (allocation dynamique fonction malloc)

Intrt : seul lespace rellement ncessaire est rserv


Cours C - Nazha SELMAOUI 115

Les directives au prprocesseur

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, )

Cours C - Nazha SELMAOUI

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

Possibilit de spcifier d'autres rpertoires l'aide de l'option -I du compilateur (voir ci-aprs)

Cours C - Nazha SELMAOUI

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

des macros avec paramtres


#define nom(liste-de-paramtres) corps-de-la-macro : o liste-deparamtres est une liste d'identificateurs spars par des virgules ex : #define MAX(a,b) (a>b ? a : b) le prprocesseur remplacera toutes les occurrences du type MAX(x,y) par (x > y ? x : y)
Cours C - Nazha SELMAOUI 119

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 }

Et voici un exemple de code :


assign(n,v) NAMPTR n; STRING v; { IF n->namflg&N_RDONLY THEN failed(n->namid,wtfailed); ELSE replace(&n->namval,v); FI } Cours C - Nazha SELMAOUI

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

Cours C - Nazha SELMAOUI

122

La compilation conditionnelle
Exemple :
#define PROCESSEUR ALPHA #if PROCESSEUR == ALPHA
taille_long = 64;

#elif PROCESSEUR == PC
taille_long = 32;

#endif

Condition lie l'existence d'un symbole


#ifdef symbole
partie-du-programme-1

#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);

#endif si la ligne #define DEBUG existe, l'instruction for sera compile

On peut remplacer l'instruction #define DEBUG au moment de la compilation par gcc -DDEBUG fichier.c

Cours C - Nazha SELMAOUI

124

Les fonctions

Dfinition d'une fonction


C'est la donne du texte de son algorithme qu'on appelle corps de la fonction.
type nom-fonction ( type-1 arg-1, , type-n arg-n) {
[dclarations de variables locales] liste d'instructions

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

Dfinition d'une fonction


La fonction se termine par l'instruction return :
return(expression); return; expression du type de la fonction fonction sans type
int puissance (int a, int n) { if ( n == 0) return(1); return(a * puissance(a, n-1)); }

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

Appel d'une fonction


L'appel de fait par:
nom-fonction(para-1,para-2, , para-n);

Dclaration d'une fonction


C n'autorise pas les fonctions imbriques. On peut dclarer une fonction secondaire soit avant, soit aprs la fonction principale main. Toutefois, il est indispensable que le compilateur "connaisse" la fonction son appel. Elle doit imprativement tre dclare avant :
type nom-fonction ( type-1, , type-n);
Cours C - Nazha SELMAOUI 128

Dclaration d'une fonction


int puissance (int , int)p; int puissance (int a, int b) {
if (n == 0)
return(1)

return(a * puissance(a, n-1));

}
main() {
int a = 2, b = 5; printf("%d\n",puissance(a,b));

}
Cours C - Nazha SELMAOUI 129

Dure de vie des variables


Les variables manipules dans un programme C n'ont pas la mme dure de vie. 2 catgories de variables :
variables permanentes (ou statiques) : occupent une place mmoire durant toute l'excution du programme (segment de donnes). Elles sont initialises zro par le compilateur et elles sont caractrises par le mot-clef static. variables temporaires : se voient allouer une place mmoire de faon dynamique (segment de pile). Elles ne sont pas initialises. Leur place mmoire est libre la fin d'excution de la fonction secondaire. Variables dites automatique. Elles sont spcifies par le mot-clef auto (rarement utilis).

Cours C - Nazha SELMAOUI

130

Dure de vie des variables


Variable globale : variable dclare en dehors des fonctions.
int n; void fonction (); void fonction () {
n++; printf("appel numero %d\n",n); return; n est initialise 0 par le compilateur appel numero 1 appel numero 2 appel numero 3 appel numero 4 appel numero 5

} main() { int i; for (i = 0; i < 5; i++)


fonction();

Cours C - Nazha SELMAOUI

131

Dure de vie des variables


Variable locale : variable dclare l'intrieur d'une fonction (ou d'un bloc d'instruction).
int n = 10; void fonction (); n est initialise 0 par le compilateur void fonction () appel numero 1 { appel numero 1 int n = 0; appel numero 1 appel numero 1 n++; appel numero 1 printf("appel numero %d\n",n); return; } main() { int i; for (i = 0; i < 5; i++) fonction(); Cours C - Nazha SELMAOUI 132 }

Dure de vie des variables


Il est possible de dclarer une variable locale de classe statique qui reste locale une fonction mais sa valeur est conserve d'un appel au suivant : static type nom-de-variable;
int n = 10; n est initialise 0 par le compilateur void fonction (); appel numero 1 void fonction () appel numero 2 { appel numero 3 static int n; appel numero 4 n++; appel numero 5 printf("appel numero %d\n",n); return; } main() { int i; for (i = 0; i < 5; i++) fonction(); } Cours C - Nazha SELMAOUI 133

Transmission des paramtres d'une fonction


Les paramtres de fonction sont traits de la mme manire que les variables locales de classe automatique. On dit que les paramtres d'une fonction sont transmis par valeurs. Exemple :
void echange (int , int); void echange (int a, int b) { int t; printf("debut fonction :\n a = %d \t b = %d\n",a,b); t = a; a = b; b = t; printf("fin fonction : \n a = %d \t b = %d\n",a,b); return; }
Cours C - Nazha SELMAOUI 134

Transmission des paramtres d'une fonction


main() { int a = 2, b = 5; printf("debut programme principal : \n a = %d \t b = %d\n",a,b); echange(a,b); printf("fin programme principal : \n a = %d \t b = %d\n",a,b); } imprime debut programme principal : a=2 b=5 debut fonction : a=2 b=5 fin fonction : a=5 b=2 fin programme principal : a=2 b=5
Cours C - Nazha SELMAOUI 135

Transmission des paramtres d'une fonction


Pour q'une fonction modifie la valeur de ses arguments, il faut il faut passer les paramtres par adresse : void echange (int *, int*); void echange (int *adr_a, int *adr_b) { int t; t = *adr_a; *adr_a = *adr_b; *adr_b = t; return; } main() { int a = 2, b = 5; printf("debut programme principal : \n a = %d \t b = %d\n",a,b); echange(&a,&b); printf("fin programme principal : \n a = %d \t b = %d\n",a,b); Cours C - Nazha SELMAOUI 136 }

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

En principe la fonction main sans arguments e pour prototype :


int main(void)

Cours C - Nazha SELMAOUI

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

int main (int argc, char *argv[]);


Cours C - Nazha SELMAOUI 138

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);

On lance l'excutable avec deux paramtres : a.out 12 8


Cours C - Nazha SELMAOUI 139

Pointeur sur une fonction


Le langage C offre la possibilit de passer une fonction comme paramtre d'une autre fonction. On utilise un mcanisme de pointeur un pointeur sur une fonction ayant pour prototype
type fonction (type-1,type-2,,type-n);

est de type
type (*)(type-1,,type-2);

Ex :
int operateur_binaire(int a, int b, int (*f)(int, int));

sa dclaration est donne


int operateur_binaire(int , int , int (*)(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

Pointeur sur une fonction


Dans le corps de la fonction operateur_binaire on crit (*f)(a,b) :
int operateur_binaire(int a, int b, int (*f)(int, int)) { return((*f)(a,b)); }

Cours C - Nazha SELMAOUI

141

Pointeur sur une fonction


#include<stdlib.h> #include<stdio.h> #include<string.h> void usage(char *); int somme(int, int); int produit(int , int); int operateur-binaire(int, int, int (*)(int, int)); void usage(char *cmd) { printf("\nUsage : %s int [plus|fois] int\n",cmd); } int somme (int a, int b) { return(a + b); } int produit (int a, int b) { return(a * b); } int operateur_binaire (int a, int b, int (*f)(int , int)) { return((*f)(a, b)); }

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.

Cours C - Nazha SELMAOUI

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.

Cours C - Nazha SELMAOUI

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); }

la compilation se fait sparment Nazha SELMAOUI Cours C -

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

Fichier en-tte d'un fichier source :


chaque fichier source nom.c un fichier en-tte nom.h comportant les dclarations des fonctions non locales au fichier nom.c (ces fonctions sont appeles fonctions d'interface) ainsi que les dfinitions des constantes symboliques et des macros qui sont partages par les 2 fichiers.
Cours C - Nazha SELMAOUI 148

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 :

Cours C - Nazha SELMAOUI

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; }

gcc produit.c main.c

Cours C - Nazha SELMAOUI

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.c se compose :


variables permanentes des fonctions d'interface dont la dclaration se trouve dans nom.h ventuelles fonctions locales nom.c

le fichier nom.h est inclus dan nom.c et dans tous les fichiers qui font appel une fonction dfinies dans nom.c

Cours C - Nazha SELMAOUI

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

Cours C - Nazha SELMAOUI

153

Cration d'un Makefile


Cible : liste de dpendances <TAB> commande UNIX fichier cible ensuite la liste des fichiers dont il dpend (spars par des espaces) aprs <TAB> il y a les commandes (compilation) UNIX excuter dans le cas o l'un des fichiers de dpendances est plus rcent que le fichier cible.
## Premier exemple de Makefile prod : produit.c main.c produit.h
gcc -o prod produit.c main.c

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

Cration d'un Makefile


Dans le premier exemple on n'utilise pas pleinement les fonctionnalits de make
## Deuxieme exemple de Makefile prod : produit.o main.o
gcc -o prod produit.o main.o

main.o : main.c produit.h


gcc -c main.c

produit.o : produit.c produit.h


gcc -c produit.c

On peut rajouter, si on veut tre bien organis, une cible appele clean permettant de nettoyer le rpertoire courant :
clean : rm -f prod *.o

Cours C - Nazha SELMAOUI

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

main.o : main.c produit.h


$(CC) -c main.c

produit.o : produit.c produit.h


$(CC) -c produit.c
Cours C - Nazha SELMAOUI 156

Vous aimerez peut-être aussi