You are on page 1of 20

Programmation II : Concepts avancs du langage C

Chapitre 1 : Programmation modulaire


et les fonctions
Sommaire :
I-

Introduction ......................................................................................................................... 1
Un exemple ............................................................................................................................. 2

II- Dfinition dune fonction .................................................................................................... 3


III-

L'utilisation des fonctions................................................................................................ 3

1) La dclaration des prototypes. ......................................................................................... 4


2) La dclaration de fonction. .............................................................................................. 4
3) L'appel de fonction: ......................................................................................................... 4
4) Exemples de dfinition .................................................................................................... 5
5) Situation de la dclaration ............................................................................................... 7
IV-

Mode de transmission des paramtres et ports des variables ....................................... 9

1) Passage par valeur ......................................................................................................... 10


2) Variable globale ............................................................................................................ 10
3) Variable locale............................................................................................................... 12
4) Les variables locales automatiques ............................................................................... 12
5) Les variables locales statiques....................................................................................... 13
6) Le cas des fonctions rcursives ..................................................................................... 13
V- La compilation spare et ses consquences..................................................................... 14
1) La porte dune variable globale - la dclaration extern ............................................... 15
2) Les variables globales et ldition de liens.................................................................... 15
3) Les variables globales caches- la dclaration static.................................................... 16
4) Tableau rcapitulatif ...................................................................................................... 17
Exercices : ................................................................................................................................ 18

I-

Introduction

Un long programme est difficile apprhender globalement. Il vaut donc mieux le scinder en
petits programmes : un programme principal fait appel des sous-programmes, qui

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

peuvent eux-mmes faire appel des sous-programmes, du programme principal ou de celuici, et ainsi de suite. Cest le principe du raffinement successif. De plus certains sousprogrammes peuvent servir dans dautres programmes, cest le principe de la modularit. Ces
principes sont mis en uvre en langage C grce aux fonctions.
On peut distinguer, en langage C, les fonctions prdfinies des bibliothques (telles que
printf() ou scanf()), livres avec le compilateur et intgres au programme lors de
ldition des liens, et les fonctions que le programmeur crit lui-mme en tant que partie du
texte source. Nous avons dj vu comment utiliser les premires dans le module
programmation 1. Nous allons donc nous intresser ici aux secondes. Nous verrons aussi,
dailleurs, la faon de concevoir les fonctions prdfinies.

Un exemple
Commenons par donner un exemple simple de dfinition et dutilisation dune fonction.
Considrons nouveau, pour cela, notre exemple de fonction que lon veut valuer en un
certain nombre de points. Une nouvelle amlioration consiste dgager la dfinition de la
fonction en utilisant un sous-programme.
Programme : La mise en place suivante est intuitivement comprhensible, nous la
dtaillerons ensuite :
/* Fonct_1.c */
#include <stdio.h>
#include <math.h>
double f(double x)
{
return((sin(x) + log(x))/(exp(x) + 2));
}
void main(void)
{
float x, y;
printf("x = ");
scanf("%f",&x);
while (x != 1000)
{
y = f(x);
printf("f(%f) = %f\n", x, y);
printf("x = ");
scanf("%f",&x);
}
}
Lamlioration provient ici plus particulirement du fait que lon ne soccupe pas de la
fonction particulire dans le corps du programme, mais uniquement du fait que lon veut
afficher sa valeur en un certain nombre de points, ce qui est lessence du programme. Il suffit
de changer le sous-programme, bien mis en vidence, lorsquon veut changer de fonction.

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

II-

Dfinition dune fonction

La dfinition des fonctions, dans des cas simples, est suffisamment claire au vu du
programme Prcdent. Mais lexplicitation suivante donne les limites dune utilisation
intuitive.
Une fonction ou procdure ou encore sous programme est une suite d'instructions
lmentaires, mais vue du programme principal main(), elle reprsente une seule action.
Elle est la base des langages structurs.
En effet, l'criture de tout programme commence par dfinir un algorithme qui dcrit
l'enchanement de toutes les actions (fonctions). La ralisation d'un algorithme c'est la
dcomposition en une suite de fonctions simples pouvant raliser une ou plusieurs fonctions
beaucoup plus compliques. Un algorithme doit tre le plus clair possible.

Une fonction est caractrise par un appel et un retour.


- L'appel est effectu par le programme principal main() ou une autre procdure.
- Le retour s'effectue aprs la dernire action de la fonction appele et le programme
continue juste aprs l'appel de la fonction.
Une fonction peut appeler une autre fonction. Le nom donn une fonction doit tre
reprsentatif de la fonction ralise (exemple : perimetre_cercle pour une procdure calculant
le primtre d'un cercle).
Le programme principal main() et les fonctions ont besoin de se communiquer des valeurs.
Lors d'un appel d'une procdure les valeurs passes sont les paramtres d'entre et la fin
d'une fonction les paramtres renvoys sont les paramtres de sortie.

III-

L'utilisation des fonctions.

La dclaration se fait en deux temps:

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

1) La dclaration des prototypes.


Elle permet de dfinir au compilateur les paramtres d'entre et de sortie afin de pouvoir
vrifier lors d'appel de fonction l'ordre de passage des paramtres. La dclaration de prototype
se diffrencie de la dclaration de fonction par lajout dun point virgule ; en fin de ligne. Elle
est situe au dbut du programme.
Syntaxe:
<type_iden_sortie> iden_fonc(<type> iden_1,..., <type> iden_n);

type_iden_sortie: type de lidentificateur du paramtre de sortie.


iden_fonc: identificateur de fonction.
iden_1: identificateur du paramtre 1 d'entre.
iden_n: identificateur du paramtre n d'entre.

2) La dclaration de fonction.
Elle dcrit l'enchanement de toutes les instructions permettant de raliser la fonction. Une
variable dclare dans une fonction est locale celle-ci et elle n'a aucune existence en dehors
de la fonction.
Syntaxe:
<type_iden_sortie> iden_fonc(<type> iden_1,..., <type> iden_n)
{
/* Dclaration de variable(s) locale(s) */
<type> iden_2,...,iden_m;
.
.
.
/* renvoie dans le paramtre de sortie */
return(valeur);
}

type_iden_sortie: type de lidentificateur du paramtre de sortie.


iden_fonc: identificateur de fonction.
iden_1: identificateur du paramtre 1 d'entre.
iden_n: identificateur du paramtre n d'entre.
Iden_2: identificateur 2 de variable locale.
iden_m: identificateur m de variable locale.

3) L'appel de fonction:
Il dirige le programme principal ou une autre fonction sur la fonction excuter en donnant
les variables d'entres et ou l'affectation de la variable de sortie.
Syntaxe:
iden_var_sortie = iden_fonc(iden_1_var,...,iden_n_var) ;
ou
iden_fonc.(iden_1_var,...,iden_n_var) ;

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

iden_var_sortie: identificateur de sortie.


iden_fonc: identificateur de fonction.
iden_1_var: identificateur du paramtre 1 d'entre.
iden_n_var: identificateur du paramtre n d'entre.

4) Exemples de dfinition
Donnons quelques exemples varies de dfinitions pour illustrer ce que nous venons de dire.
Exemple 1.- (La fonction sinc)
La fonction f dfinie par lexpression f(x) = sin(x)/x est a priori dfinie sur R*, mais on sait la
prolonger par continuit en 0 en lui attribuant la valeur 1. Ceci permet de dfinir la fonction
suivante :
double f(double x)
{
double y;
if (x == 0) y = 1;
else y = sin(x)/x;
return(y);
}
Ou
double f(double x)
{
if (x == 0) return(1);
else return(sin(x)/x));
}
Ceci nous donne un exemple avec deux utilisations de return, cause de la dfinition par cas.
Exemple 2.- (Lexponentiation)
Programmons lexponentiation, cest--dire lapplication de RN dans R qui au couple (x, n)
associe :
double puiss(double x, int n)
{
double y;
int i;
y = 1;
for (i=1; i <= n; i++) y = y*x;
return(y);
}

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

Cet exemple est intressant plusieurs titres : la fonction a deux paramtres et, de plus, de
types diffrents ; le corps comporte des dclarations de variables, dites variables locales ; on
utilise une boucle pour dfinir la fonction. On remarquera que nous sommes obligs
dintroduire la variable locale y car puiss ne pourrait pas tre utilise droite dune affectation.
Exemple 3.- (Fonction sans paramtre)
Considrons le programme suivant :
/* intro.c */
#include <stdio.h>
void welcome(void)
{
printf("Welcome to this fantastic program");
printf("\nwhich proves to you the power");
printf("\nof the modularity. \n");
}
void bienvenue(void)
{
printf("Bienvenue dans ce merveilleux");
printf("\nprogramme qui vous montre la");
printf("\npuissance de la modularite. \n");
}
void main(void)
{
char c;
printf("Do you want to continue in");
printf("\nEnglish or in French (E/F) ");
scanf("%c",&c);
if (c == E) welcome();
else bienvenue();
}
Les fonctions welcome() et bienvenue() nont ni paramtre ni valeur de retour. Remarquons
cependant lutilisation du type void et le couple de parenthses pour lappel de ces fonctions.
Le fait quil ny ait pas de type de retour rend lutilisation de return superflue.
Exemple 4.- (Le pgcd)
Nous avons dj rencontr des exercices sur le calcul du pgcd de deux entiers non nuls,
lutilisation des fonctions amliore successivement les algorithmes pour le calculer. Le
programme suivant repose sur lalgorithme dEuclide.
int pgcd(int a, int b)
{
int r;
r = 1;
while (r != 0)
{
r = a % b;
a = b;

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

b = r;
}
return(a);
}
Cet exemple est intressant pour deux raisons : la fonction a deux paramtres de mme type et
lalgorithme est non trivial.

5) Situation de la dclaration
La dclaration locale dune fonction se fait au dbut du bloc de la dfinition dune fonction,
avant les dclarations de variables. La fonction ainsi dclare nest connue que de la fonction
dans laquelle elle est dclare. On peut aussi utiliser une dclaration globale dune fonction
avant toute dfinition de fonction.
Exemple de dclaration locale :
Le programme suivant illustre la notion de dclaration locale de fonction :
/* dec_loc.c */
#include <stdio.h>
#include <math.h>
void main(void)
{
double f(double x);
float x, y;
printf("x = ");
scanf("%f",&x);
while (x != 1000)
{
y = f(x);
printf("f(%f) = %f\n", x, y);
printf("x = ");
scanf("%f",&x);
}
}
double f(double x)
{
return((sin(x) + log(x))/(exp(x) + 2));
}
Exemple de dclaration globale :
Le programme suivant illustre la notion de dclaration globale de fonction :
/* dec_glo.c */
#include <stdio.h>
#include <math.h>
double f(double x);
void main(void)

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

{
float x, y;
printf("x = ");
scanf("%f",&x);
while (x != 1000)
{
y = f(x);
printf("f(%f) = %f\n", x, y);
printf("x = ");
scanf("%f",&x);
}
}
double f(double x)
{
return((sin(x) + log(x))/(exp(x) + 2));
}
Pragmatique : Pour mettre un peu dordre dans un programme faisant intervenir beaucoup de
fonctions, on peut commencer par la dfinition de la fonction principale, prcde de la
dclaration des fonctions dont elle a besoin. On dfinit ensuite ces fonctions auxiliaires,
chacune delles prcde des dclarations des fonctions auxiliaires de second niveau dont
elles ont besoin, et ainsi de suite.
Dclaration de fonctions dans des fichiers en-tte :
La dclaration dune fonction personnelle ne doit pas ncessairement tre incluse
explicitement dans le mme fichier du programme source que la fonction principale. Elle peut
aussi se trouver dans un fichier en-tte, comme pour les fonctions prdfinies. Ce dernier est
ensuite insr dans le programme grce une commande du prprocesseur.
Exemple : En mettant dans le mme rpertoire les deux fichiers suivants :
/* calcul.c */
#include <stdio.h>
#include <math.h>
#include "defini.h"
void main(void)
{
float x, y;
printf("x = ");
scanf("%f",&x);
while (x != 1000)
{
y = f(x);
printf("f(%f) = %f\n", x, y);
printf("x = ");
scanf("%f",&x);
}
}

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

et :
/* defini.h */
double f(double x)
{
return((sin(x) + log(x))/(exp(x) + 2));
}
On obtient un programme correct qui fonctionne.
Commentaires :

Le fichier en-tte definiti.h contient ici non pas la dclaration dune fonction mais sa
dfinition. On place en principe le code des fonctions directement dans le programme
ou dans des bibliothques. Les dfinitions des fonctions livres avec le compilateur se
trouvent (sous forme de code objet) dans de telles bibliothques ayant lextension .lib
(pour LIBrary).

Le fichier en-tte est crit entre guillemets verticaux " et non entre les symboles < et >
car il ne se trouve pas dans le rpertoire standard des en-ttes mais dans le rpertoire
contenant le programme source. On peut aussi indiquer le chemin complet, par
exemple en MS-DOS (Windows) : #include "c:\tcwin\programmes\definiti.h"

IV-

Mode de transmission des paramtres et ports des variables

Pour une fonction mathmatique f deux arguments, lorsquon value cette fonction, en
effectuant par exemple y = f(a, b), on sattend ce que la valeur de y soit change mais pas
les valeurs de a ou de b. En informatique il en va autrement. On peut, par exemple, dsirer
crire un sous-programme :
echange(a,b) dont le but est dchanger les valeurs de a et de b. Nous savons crire le corps
de ce programme en langage C depuis longtemps. Par exemple si a et b sont des entiers on a :
int c;
c = a;
a = b;
b = c;
Comment crire le sous-programme correspondant dans un langage de programmation ?
Passage par valeur et passage par rfrence : Lorsquon ne veut pas changer la valeur dun
paramtre on parle de transmission par valeur (en anglais call by value), cest--dire que le
Sous-programme ne reoit quune copie de la valeur. Lorsquon veut se permettre la
possibilit de changer la valeur on parle de transmission par reference (en anglais call by
reference).

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

Programmation II : Concepts avancs du langage C

Mise en place : Beaucoup de langages permettent ces deux types de transmission. Cest le
cas, par exemple, du langage PASCAL. Le langage C, quant lui, ne connait que la
transmission par valeur, la transmission par rfrence est mule en envoyant la valeur de
ladresse grce aux pointeurs (comme nous le verrons dans le chapitre 2 : La

programmation modulaire et les pointeurs).


1) Passage par valeur
Voyons sur deux exemples le comportement de la transmission par valeur.
Exemple 1. Considrons le programme suivant :
/* valeur_1.c */
#include <stdio.h>
void affiche(int n)
{
printf("%d \n", n);
}
void main(void)
{
int n = 3;
affiche(n);
}
Son excution fait afficher 3 comme attendu.
Exemple 2 : Considrons le programme modifie suivant :
/* valeur_2.c */
#include <stdio.h>
void affiche(int n)
{
n = 4;
printf("%d \n", n);
}
void main(void)
{
int n = 3;
affiche(n);
printf("%d \n", n);
}
Son excution fait afficher 4 puis 3. La fonction affiche() na donc pas chang la valeur de n
dans la fonction principale.

2) Variable globale
Une variable globale est une variable dclare avant toute dfinition de fonction. Lintrt est
quelle est alors connue de toutes les fonctions, on peut donc changer sa valeur dans chacune

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

10

Programmation II : Concepts avancs du langage C

delle. Linconvnient est quon peut aussi changer sa valeur par inattention. Il vaut donc
mieux utiliser le passage par rfrence quune variable globale. Voyons cependant comment
cela fonctionne.
Exemple 1.- Considrons le programme suivant :
/* global_1.c */
#include <stdio.h>
int n = 3;
void affiche(void)
{
n = 4;
printf("%d \n", n);
}
void main(void)
{
affiche();
printf("%d \n", n);
}
Lexcution de ce programme fait afficher 4 puis 4. La fonction affiche() a donc chang la
valeur de n dans la fonction principale.
Remarque : Lutilisation des variables globales dans un programme est permise, mais il vaut
mieux viter de sen servir. Cela va en effet lencontre de la clart de la modularit.
Lorsquon considre un sous-programme on devrait voir dun seul coup dil toutes les
variables qui y interviennent. Cest tout lintrt des arguments.
Exemple 2 : Remarquons que, dans le cas de la variable globale ci-dessus, la fonction
affiche() navait pas dargument. Considrons, par opposition, le programme suivant :
/* global_2.c */
#include <stdio.h>
int n = 3;
void affiche(int n)
{
n = 4;
printf("%d \n", n);
}
void main(void)
{
affiche(n);
printf("%d \n", n);
}
Son excution fait afficher 4 puis 3. La dclaration de largument n dans la fonction affiche()
le fait considrer comme une variable locale. La variable n du corps de cette fonction
correspond la dernire variable dclare, donc la variable locale, et non la variable
globale ; ceci explique pourquoi la valeur de la variable globale, elle, na pas change.
La classe dallocation des variables globales

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

11

Programmation II : Concepts avancs du langage C

Dune manire gnrale, les variables globales existent pendant toute lexcution du
programme dans lequel elles apparaissent. Leurs emplacements en mmoire sont parfaitement
dfinis lors de ldition de liens. On traduit cela en disant quelles font partie de la classe
dallocation statique.
De plus, ces variables se voient initialises zro, avant le dbut de lexcution du
programme, sauf, bien sr, si vous leur attribuez explicitement une valeur initiale au moment
de leur dclaration.

3) Variable locale
La procdure elle-mme peut avoir besoin de variables qui nont pas dintrt pour le
programme en son entier, comme nous lavons vu propos de la fonction puiss(). On parle
alors de variable locale.
Remarque : Le nom de variable locale se justifie de par la position de sa dclaration. Elle se
justifie aussi car une telle variable nest pas connue du programme dans son entier mais
uniquement de la fonction (plus gnralement du bloc) dans laquelle elle a t dclare.
Ceci montre lintrt dutiliser le plus possible des variables locales : cest une protection
Supplmentaire contre les erreurs de programmation.
Nom dune variable locale : Nous avons dit prcdemment (avant de considrer les
fonctions) quon ne peut pas dclarer le mme identificateur comme variable deux endroits
diffrents. Il faut assouplir un petit peu cette rgle avec lutilisation des sous-programmes : en
effet, pour un (gros) programme, des sous-programmes diffrents peuvent tre conus par des
personnes diffrentes, qui peuvent donc penser au mme nom de variable ; ceci sera dtect
lors de la compilation, certes, mais cela risque de ne pas faciliter les choses. On permet donc
en gnral, dans un langage de programmation, la possibilit dutiliser un mme identificateur
plusieurs fois comme variable locale.
Priorit des variables locales sur les variables globales : Un problme se pose alors :
Quelle est la variable considre lors de son utilisation ?
La rponse est simple : celle qui a t dclare le plus rcemment, cest -dire la plus locale
lintrieur du sous-programme (et, plus gnralement, lintrieur du bloc).

4) Les variables locales automatiques


Par dfaut, les variables locales ont une dure de vie limite celle dune excution de la
fonction dans laquelle elles figurent. Plus prcisment, leurs emplacements ne sont pas dfinis
de manire permanente comme ceux des variables globales. Un nouvel espace mmoire leur
est allou chaque entre dans la fonction et libr chaque sortie. Il sera donc gnralement
diffrent dun appel au suivant.
On traduit cela en disant que la classe dallocation de ces variables est automatique. Nous
aurons loccasion de revenir plus en dtail sur cette gestion dynamique de la mmoire. Pour
linstant, il est important de noter que la consquence immdiate de ce mode dallocation est
que les valeurs des variables locales ne sont pas conserves dun appel au suivant (on dit aussi
quelles ne sont pas rmanentes ).

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

12

Programmation II : Concepts avancs du langage C

Dautre part, les valeurs transmises en arguments une fonction sont traites de la mme
manire que les variables locales. Leur dure de vie correspond galement celle de la
fonction.

5) Les variables locales statiques


Il est toutefois possible de demander dattribuer un emplacement permanent une variable
locale et quainsi sa valeur se conserve dun appel au suivant. Il suffit pour cela de la dclarer
laide du mot-cl static (le mot static employ sans indication de type est quivalent static
int).
En voici un exemple :
#include <stdio.h>
main()
{
void fct(void) ;
int n ;
for ( n=1 ; n<=5 ; n++)
fct() ;
}
void fct(void)
{
static int i ;
i++ ;
printf ("appel numro : %d\n", i) ;
}
Rsultat :
appel numro : 1
appel numro : 2
appel numro : 3
appel numro : 4
appel numro : 5
La variable locale i a t dclare de classe statique . On constate bien que sa valeur
progresse de un chaque appel. De plus, on note quau premier appel sa valeur est nulle. En
effet, comme pour les variables globales (lesquelles sont aussi de classe statique) : les
variables locales de classe statique sont, par dfaut, initialises zro.
Prenez garde ne pas confondre une variable locale de classe statique avec une variable
globale. En effet, la porte dune telle variable reste toujours limite la fonction dans
laquelle elle est dfinie. Ainsi, dans notre exemple, nous pourrions dfinir une variable
globale nomme i qui naurait alors aucun rapport avec la variable i de fct.

6) Le cas des fonctions rcursives

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

13

Programmation II : Concepts avancs du langage C

Le langage C autorise la rcursivit des appels de fonctions. Celle-ci peut prendre deux
aspects :

Rcursivit directe : une fonction comporte, dans sa dfinition, au moins un appel


elle-mme,
Rcursivit croise : lappel dune fonction entrane celui dune autre fonction qui,
son tour, appelle la fonction initiale (le cycle pouvant dailleurs faire intervenir plus de
deux fonctions).

Voici un exemple fort classique (dailleurs inefficace sur le plan du temps dexcution) dune
fonction calculant une factorielle de manire rcursive :
long fac (int n)
{
if (n>1) return (fac(n-1)*n) ;
else return(1) ;
}
Il faut bien voir qualors chaque appel de fac entrane une allocation despace pour les
variables locales et pour son argument n (apparemment, fac ne comporte aucune variable
locale ; en ralit, il lui faut prvoir un emplacement destin recevoir sa valeur de retour).
Or chaque nouvel appel de fac, lintrieur de fac, provoque une telle allocation, sans que les
emplacements prcdents soient librs.
Il y a donc un empilement des espaces allous aux variables locales, paralllement un
empilement des appels de la fonction. Ce nest que lors de lexcution de la premire
instruction return que lon commencera dpiler les appels et les emplacements et donc
librer de lespace mmoire.

V-

La compilation spare et ses consquences

Si le langage C est effectivement un langage que lon peut qualifier doprationnel, cest en
partie grce ses possibilits dites de compilation spare. En C, en effet, il est possible de
compiler sparment plusieurs programmes (fichiers) source et de rassembler les modules
objet correspondants au moment de ldition de liens. Dailleurs, dans certains
environnements de programmation, la notion de projet permet de grer la multiplicit des
fichiers (source et modules objet) pouvant intervenir dans la cration dun programme
excutable.
Cette notion de projet fait intervenir prcisment les fichiers considrer ; gnralement, il est
possible de demander de crer le programme excutable, en ne recompilant que les sources
ayant subi une modification depuis leur dernire compilation.
Indpendamment de ces aspects techniques lis lenvironnement de programmation
considr, les possibilits de compilation spare ont une incidence importante au niveau de
la porte des variables globales. Cest cet aspect que nous nous proposons dtudier
maintenant. Dans le paragraphe suivant, nous serons alors en mesure de faire le point sur les
diffrentes classes dallocation des variables.

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

14

Programmation II : Concepts avancs du langage C

Notez que, partir du moment o lon parle de compilation spare, il existe au moins (ou il a
exist) deux programmes source ; dans la suite, nous supposerons quils figurent dans des
fichiers, de sorte que nous parlerons toujours de fichier source.
Pour linstant, voyons lincidence de cette compilation spare sur la porte des variables
globales.

1) La porte dune variable globale - la dclaration extern


A priori, la porte dune variable globale semble limite au fichier source dans lequel elle a
t dfinie. Ainsi, supposez que lon compile sparment ces deux fichiers source :
source 1
int x ;
main()
{
.....
}
fct1()
{
.....}

source 2
fct2()
{
.....
}
fct3()
{
.....
}

Il ne semble pas possible, dans les fonctions fct2 et fct3 de faire rfrence la variable
globale x dclare dans le premier fichier source (alors quaucun problme ne se poserait si
lon runissait ces deux fichiers source en un seul, du moins si lon prenait soin de placer les
instructions du second fichier la suite de celles du premier).
En fait, le langage C prvoit une dclaration permettant de spcifier quune variable globale a
dj t dfinie dans un autre fichier source. Celle-ci se fait laide du mot-cl extern. Ainsi,
en faisant prcder notre second fichier source de la dclaration : extern int x ;
Il devient possible de mentionner la variable globale x (dclare dans le premier fichier
source) dans les fonctions fct2 et fct3.
Remarque : Cette dclaration extern neffectue pas de rservation demplacement de
variable. Elle ne fait que prciser que la variable globale x est dfinie par ailleurs et elle en
prcise le type.

2) Les variables globales et ldition de liens


Supposons que nous ayons compil les deux fichiers source prcdents et voyons dun peu
plus prs comment lditeur de liens est en mesure de rassembler correctement les deux
modules objet ainsi obtenus. En particulier, examinons comment il peut faire correspondre au
symbole x du second fichier source ladresse effective de la variable x dfinie dans le premier.
Dune part, aprs compilation du premier fichier source, on trouve, dans le module objet
correspondant, une indication associant le symbole x et son adresse dans le module objet.
Autrement dit, contrairement ce qui se produit pour les variables locales, pour lesquelles ne

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

15

Programmation II : Concepts avancs du langage C

subsiste aucune trace du nom aprs compilation, le nom des variables globales continue
exister au niveau des modules objet. On retrouve l un mcanisme analogue ce qui se passe
pour les noms de fonctions, lesquels doivent bien subsister pour que lditeur de liens soit en
mesure de retrouver les modules objet correspondants.
Dautre part, aprs compilation du second fichier source, on trouve dans le module objet
correspondant, une indication mentionnant quune certaine variable de nom x provient de
lextrieur et quil faudra en fournir ladresse effective.
Ce sera effectivement le rle de lditeur de liens que de retrouver dans le premier module
objet ladresse effective de la variable x et de la reporter dans le second module objet.
Ce mcanisme montre que sil est possible, par mgarde, de rserver des variables globales de
mme nom dans deux fichiers source diffrents, il sera, par contre, en gnral, impossible
deffectuer correctement ldition de liens des modules objet correspondants (certains diteurs
de liens peuvent ne pas dtecter cette anomalie). En effet, dans un tel cas, lditeur de liens se
trouvera en prsence de deux adresses diffrentes pour un mme identificateur, ce qui est
illogique.

3) Les variables globales caches- la dclaration static


Il est possible de cacher une variable globale, cest--dire de la rendre inaccessible
lextrieur du fichier source o elle a t dfinie (on dit aussi rendre confidentielle au lieu
de cacher ; on parle alors de variables globales confidentielles ). Il suffit pour cela
dutiliser la dclaration static comme dans cet exemple :
static int a ;
main()
{
.....
}
fct()
{
.....
}
Sans la dclaration static, a serait une variable globale ordinaire. Par contre, cette dclaration
demande quaucune trace de a ne subsiste dans le module objet rsultant de ce fichier source.
Il sera donc impossible dy faire rfrence depuis une autre source par extern.
Mieux, si une autre variable globale apparat dans un autre fichier source, elle sera accepte
ldition de liens puisquelle ne pourra pas interfrer avec celle du premier fichier source.
Cette possibilit de cacher des variables globales peut savrer prcieuse lorsque vous tes
amen dvelopper un ensemble de fonctions dintrt gnral qui doivent partager des
variables globales. En effet, elle permet lutilisateur ventuel de ces fonctions de ne pas
avoir se soucier des noms de ces variables globales puisquil ne risque pas alors dy accder
par mgarde. Cela gnralise en quelque sorte tout un fichier source la notion de variable
locale telle quelle tait dfinie pour les fonctions. Ce sont dailleurs de telles possibilits qui
permettent de dvelopper des logiciels en C, en utilisant une philosophie oriente objet.

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

16

Programmation II : Concepts avancs du langage C

Remarque : Le cas des fonctions. La fonction est considre par le langage C comme un objet
global. Cest ce qui permet dailleurs lditeur de liens deffectuer correctement son travail.
Il faut noter toutefois quil nest pas ncessaire dutiliser une dclaration extern pour les
fonctions dfinies dans un fichier source diffrent de celui o elles sont appeles (mais le faire
ne constitue pas une erreur).
En tant quobjet global, la fonction peut voir sa porte limite au fichier source dans lequel
elle est dfinie laide dune dclaration static comme dans : static int fct (...)

4) Tableau rcapitulatif
Voici un tableau rcapitulant la porte et la classe dallocation des diffrentes variables
suivant la nature de leur dclaration (la colonne Type donne le nom quon attribue
usuellement de telles variables).

Type, porte et classe dallocation des variables

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

17

Programmation II : Concepts avancs du langage C

Exercices :
Exercice 1

Ecrire une fonction SOMME de type float qui calcule la somme de deux nombres rels.
Ecrire une fonction MOYENNE de type float qui calcule la moyenne arithmtique de deux
nombres rels.
Ecrire un programme se servant de ces deux fonctions pour afficher la somme et la moyenne de deux
nombres rels saisis au clavier.

Exercice 2
Ecrire une fonction MIN et une fonction MAX qui dterminent le minimum et le maximum de deux
nombres rels.
Ecrire un programme se servant des fonctions MIN et MAX pour dterminer le minimum et le
maximum de :
deux nombres rels entrs au clavier.
Quatre nombre rels entrs au clavier.

Exercice 3
crire une fonction rcursive calculant la valeur de la fonction dAckermann A dfinie
Pour m>0 et n>0 par :
A(m,n) = A(m-1,A(m,n-1)) pour m>0 et n>0
A(0,n) = n+1 pour n>0
A(m,0) = A(m-1,1) pour m>0

Exercice 4
Ecrire un programme se servant d'une fonction F pour afficher la table de valeurs de la fonction
dfinie par : f(x) = sin(x) + ln(x) O x est un entier compris entre 1 et 10.

Exercice 5
1. Ecrire la fonction ECRIRE_TAB deux paramtres TAB (un tableau de type int) et N (la
taille du tableau) qui affiche les N valeurs du tableau TAB.
2. Ecrire la fonction SOMME_TAB qui calcule la somme des N lments d'un tableau

TAB du type int. N et TAB sont fournis comme paramtres; la somme est retourne
comme rsultat du type long.
A l'aide des fonctions prcdentes, crire un programme qui lit un tableau A d'une dimension
infrieure ou gale 100 et affiche le tableau et la somme des lments du tableau.
Exercice 6
1. Ecrire une fonction DOUBLE qui remplace un nombre rel X par son double (2*X)
2. Ecrire une fonction qui change le contenu de deux variables.

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

18

Programmation II : Concepts avancs du langage C

Tester ces deux fonctions l'aide de valeurs lues au clavier.


Exercice 7
Ecrire deux fonctions qui calculent la valeur XN pour une valeur relle X (type double) et une valeur
entire positive N (type int) en utilisant seulement la multiplication :
1. EXP1 retourne la valeur XN comme rsultat.
2. EXP2 affecte la valeur XN X et ne retourne rien.
Ecrire un programme qui teste les deux fonctions l'aide de valeurs lues au clavier.

Exercice 8
Ecrire une fonction qui prend comme paramtres un entier X, un tableau A de type int , et la taille du
tableau A et limine toutes les occurrences de X dans A en tassant les lments restants.
Ecrire un programme qui teste cette fonction l'aide de valeurs lues au clavier.

Exercice 9
Ecrire une fonction INVERSE qui range les lments d'un tableau A de type int dans l'ordre inverse.
Ecrire un petit programme qui teste la fonction INVERSE.

Exercice 10
Ecrire la fonction NCHIFFRES de type int qui obtient une valeur entire N (positive ou ngative) de
type long comme paramtre et qui fournit le nombre de chiffres de N comme rsultat.
Ecrire un petit programme qui teste la fonction NCHIFFRES:
Exemple:
Introduire un nombre entier : 6457392
Le nombre 6457392 a 7 chiffres.

Exercice 11
Ecrire un programme qui construit et affiche le triangle de Pascal en calculant les coefficients
binomiaux:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
. . .
On n'utilisera pas de tableau, c.--d. il faudra calculer les coefficients d'aprs la formule ci-dessous,
tout en dfinissant et utilisant les fonctions adquates.

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

19

Programmation II : Concepts avancs du langage C

Avec p : le numro de la ligne, et q : le numro de la colonne o se trouve le coefficient binomial.


Exemple : le coefficient 2 qui est dans la ligne 2 et la colonne 1 est le rsultat de : 2!/(1!*(2-1)!)

Exercice 12
On souhaite crer un programme d'annuaire trs simplifi qui associe un nom de personne
un numro de tlphone :
1. Crer une structure Personne pouvant contenir ces informations (nom et tlphone).
Le nom peut contenir 32 caractres et le numro 16 caractres.
2. Crer une nouvelle structure qui va reprsenter le carnet d'adresses. Cette structure
Carnet contiendra un tableau de 20 Personnes et un compteur indiquant le nombre de
personnes dans le tableau.
3. Crer ensuite une fonction qui cre et qui renvoie une structure Personne contenant un
nom et un tlphone passs en argument.
4. Rajouter une fonction qui affiche les informations contenues dans la structure
Personne passe en argument.
5. Crer une fonction qui ajoute une personne dans un carnet, lajout se fait par insertion,
le carnet doit rester tri par ordre alphabtique des noms aprs lajout.
6. Crer une fonction qui recherche un contact dans le carnet par nom, la fonction
retourne lindice de la personne recherche ou -1 si le contact nexiste pas.
7. Crer une fonction qui affiche un carnet.
8. Crer une fonction qui supprime un contact du carnet, la fonction prend en paramtre
le carnet, le nom du contact et retourne le nouveau carnet.
9. A partir des tapes prcdentes, faire un programme grant un carnet d'adresse. Crer
un menu qui propose d'ajouter une nouvelle personne, de supprimer une personne, de
rechercher une personne par nom, d'afficher le carnet ou de quitter:
1 : pour ajouter un contact
2 : pour supprimer un contact
3 : pour afficher la liste des contacts
4 : pour rechercher un contact par nom
5 : pour quitter le programme
Entrez votre choix [1-5] :

Pr Rachid DEHBI, Facult des sciences Ain Chock, Dpartement MATH/INFO

20

You might also like