sommaire du chapitre :
1. Modularisation de programmes
1a. La modularité et ses avantages
1b. Exemples de modularisation en C2. La notion de blocs et la portée des identificateurs
2a. Variables locales
2b. Variables globales3. Déclaration et définition de fonctions
3a. Définition d'une fonction
3b. Déclaration d'une fonction
5. Paramètres d'une fonction
5a. Généralités
5b. Passage des paramètres par valeur
5c. Passage de l'adresse d'une variable
5d. Passage de l'adresse d'un tableau à une dimension
5e. Passage de l'adresse d'un tableau à deux dimensions
La structuration de programmes en sous-programmes se fait en C à l'aide de
fonctions.
Les fonctions en C correspondent aux fonctions et procédures en Pascal et en
langage algorithmique.
Nous avons déjà utilisé des fonctions prédéfinies dans des bibliothèques standard
(printf de
1.Modularisation de programmes
Jusqu'ici, nous avons résolu nos problèmes à l'aide de fonctions
prédéfinies et d'une seule fonction nouvelle: la fonction principale main().
Pour des problèmes plus complexes, nous obtenons ainsi de longues listes d'instructions,
peu structurées et par conséquent peu compréhensibles.
En plus, il faut souvent répéter les mêmes suites de commandes dans le texte
du programme, ce qui entraîne un gaspillage de mémoire interne et externe.
1a. La modularité et ses avantages
La plupart des langages de programmation nous permettent de subdiviser
nos programmes en sous-programmes, fonctions ou procédures plus simples et plus
compacts.
A l'aide de ces structures nous pouvons modulariser nos programmes pour
obtenir des solutions plus élégantes et plus efficientes.
Modules
Dans ce contexte, un module désigne une entité de données et d'instructions
qui fournissent une solution à une partie bien définie d'un problème plus complexe.
Un module peut faire appel à d'autres modules, leur transmettre des données
et recevoir des données en retour.
L'ensemble des modules ainsi reliés doit alors être capable de résoudre le problème
global.
Avantages
-Meilleure lisibilité
-Diminution du risque d'erreurs
-Possibilité de tests sélectifs
-Dissimulation des méthodes
-Réutilisation de modules déjà existants
-Simplicité de l'entretien
-Favorisation du travail en équipe
-Hiérarchisation des modules
ATTENTION ! :
Si dans le texte du programme une fonction est défine après la fonction appelante,
il faut la déclarer ou bien localement à l'intérieur de la fonction appelante
ou bien globalement au début du programme.
La déclaration d'une fonction se fait à l'aide d'un "prototype" de
la fonction qui correspond en général à la première ligne (la ligne déclarative)
de la fonction.
1b. Exemples de modularisation en C
Exemple 1 : Afficher un rectangle d'étoiles
Le programme suivant permet d'afficher à l'écran un rectangle de longueur L et de hauteur H, formé d'astérisques (*) :
#include
main()
{
/* Prototypes des fonctions appelées par main */
void RECTANGLE(int L, int
H);
/* Déclaration des variables locales de main */
int L, H;
/* Traitements */
printf("Entrer la longueur (>= 1): ");
scanf("%d", &L);
printf("Entrer la hauteur (>= 1): ");
scanf("%d", &H);
/* Afficher un rectangle d'étoiles */
RECTANGLE(L,H);
return 0;
}
Pour que la fonction soit exécutable par la machine, il faut encore spécifier la fonction RECTANGLE :
void RECTANGLE(int
L, int H)
{
/* Prototypes des fonctions appelées */
void LIGNE(int L);
/* Déclaration des variables locales */
int I;
/* Traitements */
/* Afficher H lignes avec L étoiles */
for (I=0; I <H; I++)
LIGNE(L) ;
}
Pour que la fonction RECTANGLE soit exécutable par la machine, il faut spécifier la fonction LIGNE :
void LIGNE(int L)
{
/* Affiche à l'écran une ligne avec L étoiles */
/* Déclaration des variables locales */
int I;
/* Traitements */
for (I=0 ; I<L ; I++)
{ printf("*"); }
printf("\n");
}
Exemple 2 : Tableau de valeurs d'une fonction
Soit F la fonction numérique définie par F(X) = X3-2X+1.
On désire construire un tableau de valeurs de cette fonction.
Le nombre N de valeurs ainsi que les valeurs de X sont entrés au clavier par
l'utilisateur.
En modularisant ce problème, nous obtenons un programme principal
très court et bien "lisible".
La fonction main joue le rôle du programme principal :
main()
{
/* Prototypes des fonctions appelées par main */
void ACQUERIR(int *N);
void LIRE_VECTEUR(float T[], int
N);
void CALCULER_VALEURS(float X[],
float V[], int N);
void AFFICHER_TABLE(float X[], float
V[], int N);
float X[100];
/* valeurs de X */
float V[100];
/* valeurs de F(X) */
int N;
ACQUERIR(&N);
/* 1 <= N <= 100 */
LIRE_VECTEUR(X, N);
CALCULER_VALEURS(X, V, N);
AFFICHER_TABLE(X, V, N);
return 0;
}
Pour que la machine puisse exécuter ce programme, il faut encore
implémenter les modules ACQUERIR, LIRE_VECTEUR, CALCULER_VALEURS et AFFICHER_TABLE.
Ces spécifications se font en C sous forme de fonctions qui remplacent les fonctions
et les procédures que nous connaissons en langage algorithmique et en Pascal.
Une "procédure" est réalisée en C par une fonction qui fournit le
résultat void (vide).
Les fonctions sont ajoutées dans le texte du programme au-dessus ou en-dessous
de la fonction main.
Voici le code des fonctions nécessaires :
void ACQUERIR(int *N)
{
do
{
printf("Entrez un entier entre 1 et 100 : ");
scanf("%d", N);
}
while (*N<1 || *N>100) ;
}
void LIRE_VECTEUR(float
T[], int N)
{
/* Remplit un tableau T d'ordre N avec des nombres réels entrés au clavier */
/* Déclaration des variables locales */
int I;
/* Remplir le tableau */
printf("Entrez %d nombres réels :\n", N);
for (I=0; I<N; I++)
{ scanf("%f" , &T[I]) ; }
}
void CALCULER_VALEURS(float
X[], float V[], int N)
{
/* Remplit le tableau V avec les valeurs de F(X[I]) pour les N premières composantes
X[I] du tableau X */
/* Prototype de la fonction F */
float F(float X);
/* Déclaration des variables locales */
int I;
/* Calculer les N valeurs */
for (I=0; I<N; I++)
{ V[I] = F(X[I]); }
}
float F(float X)
{
/* Retourne la valeur numérique du polynôme défini par F(X) = X^3-2X+1 */
return (X*X*X - 2*X + 1);
}
void AFFICHER_TABLE(float
X[], float V[], int N)
{
/* Affiche une table de N valeurs : X contient les valeurs données et V contient
les valeurs calculées. */
/* Déclaration des variables locales */
int I;
/* Afficher le tableau */
printf("\n X : ");
for (I=0; I<N; I++) printf("%.1f", X[I]);
printf("\n F(X): ");
for (I=0; I<N; I++) ++) printf("%.1f", V[I]);
printf("\n");
}
2. La notion de blocs et la portée des identificateurs
Les fonctions en C sont définies à l'aide de blocs d'instructions.
Un bloc d'instructions est encadré d'accolades et composé de deux parties :
Blocs d'instructions en C
{
<declarations locales>
<instructions>
}
Par opposition à d'autres langages de programmation, ceci est
vrai pour tous les blocs d'instructions, et non seulement pour les blocs qui
renferment une fonction.
Ainsi, le bloc d'instructions d'une commande if, while ou for
peut théoriquement contenir des déclarations locales de variables et même de
fonctions.
Exemple :
La variable d'aide I est déclarée à l'intérieur d'un bloc conditionnel.
Si la condition (N>0) n'est pas remplie, I n'est pas défini.
A la fin du bloc conditionnel, I disparaît :
if (N>0)
{
int I;
for (I=0; I<N; I++) ...
}
Les variables déclarées dans un bloc d'instructions sont uniquement
visibles à l'intérieur de ce bloc.
On dit que ce sont des variables locales à ce bloc.
ATTENTION ! :
Une variable déclarée à l'intérieur d'un bloc cache toutes les variables
du même nom des blocs qui l'entourent.
De plus, la variable locale au bloc n'est pas accessible à l'extérieur
du bloc, mais accessible depuis tous les blocs déclarés dans
le bloc (sauf si une variable locale la cache...).
Les variables déclarées au début du fichier, à l'extérieur de
toutes les fonctions sont disponibles à toutes les fonctions du programme.
Ce sont alors des variables globales.
En général, les variables globales sont déclarées immédiatement derrière les
instructions #include au début du programme.
ATTENTION ! :
Les variables déclarées au début de la fonction principale main ne sont
pas des variables globales, mais elles sont locales à main.
Conseils
-Les variables globales sont à utiliser avec précaution, puisqu'elles
créent des liens invisibles entre les fonctions. La modularité d'un programme
peut en souffrir et le programmeur risque de perdre la vue d'ensemble.
-Il faut faire attention à ne pas cacher involontairement des variables globales
par des variables locales du même nom.
-Le codex de la programmation défensive nous conseille d'écrire nos programmes
aussi "localement" que possible.
L'utilisation de variables globales devient inévitable, si...
* plusieurs fonctions qui ne s'appellent pas ont besoin des mêmes variables
* plusieurs fonctions d'un programme ont besoin du même ensemble de variables
; ce serait alors trop encombrant de passer toutes les variables comme paramètres
d'une fonction à l'autre.
3. Déclaration et définition de fonctions
En général, le nom d'une fonction apparaît à trois endroits dans
un programme:
-lors de la déclaration
-lors de la définition
-lors de l'appel
Dans la définition d'une fonction, nous indiquons:
- le nom de la fonction
- le type, le nombre et les noms des paramètres de la fonction
- le type du résultat fourni par la fonction
- les données locales à la fonction
- les instructions à exécuter
Définition d'une fonction en langage algorithmique
Fonction
<Declaration des parametres>
<Declaration locales>
<Instructions>
FinFonction
Définition d'une fonction en C
<TypeResultat> <NomFonction>(
{
<Declaration locales>
<Instructions>
}
Remarques :
Une fonction peut fournir comme résultat:
- un type arithmétique
- une structure
- une réunion
- un pointeur
- void (la fonction correspond alors à une "procédure").
Une fonction ne peut pas fournir comme résultat
- des tableaux
- des chaînes de caractères
- des fonctions.
ATTENTION ! : Il est cependant possible de renvoyer un pointeur sur le premier
élément d'un tableau ou d'une chaîne de caractères.)
Si une fonction n'a pas de paramètres, on peut déclarer la liste des paramètres comme void ou simplement comme ().
Le type par défaut est int; autrement dit: si le type d'une fonction n'est pas déclaré explicitement, elle est automatiquement du type int.
Il est interdit de définir des fonctions à l'intérieur d'une autre fonction (comme en Pascal).
En principe, l'ordre des définitions dans le texte du programme ne joue pas de rôle, mais chaque fonction doit être déclarée ou définie avant d'être appelée
3b. Déclaration d'une fonction
En C, il faut déclarer chaque fonction avant de pouvoir l'utiliser.
La déclaration informe le compilateur du type des paramètres et du résultat
de la fonction.
A l'aide de ces données, le compilateur peut contrôler si le nombre et le type
des paramètres d'une fonction sont corrects.
Si dans le texte du programme la fonction est définie avant son premier appel,
elle n'a pas besoin d'être déclarée.
Prototype d'une fonction
La déclaration d'une fonction se fait par un prototype de la fonction qui indique uniquement le type des données transmises et reçues par la fonction.
Déclaration : Prototype d'une fonction
<TypeResultat> <NomFonction>(
ou
<TypeResultat> <NomFonction>(
Remarques :
-On peut facultativement inclure les noms des paramètres dans la déclaration,
mais ils ne sont pas considérés par le compilateur. Les noms fournissent pourtant
une information intéressante pour le programmeur qui peut en déduire le rôle
des différents paramètres.
-Il est d'usage de copier la première ligne de la définition de la fonction
comme déclaration.
Règles pour la déclaration des fonctions
De façon analogue aux déclarations de variables, nous pouvons
déclarer une fonction localement ou globalement.
La définition des fonctions joue un rôle spécial pour la déclaration.
En résumé, nous allons considérer les règles suivantes :
Déclaration locale :
Une fonction peut être déclarée localement dans la fonction qui l'appelle (avant
la déclaration des variables).
Elle est alors disponible à cette fonction.
Déclaration globale :
Une fonction peut être déclarée globalement au début du programme (derrière
les instructions #include).
Elle est alors disponible à toutes les fonctions du programme.
Déclaration implicite par la définition :
La fonction est automatiquement disponible à toutes les fonctions qui suivent
sa définition.
Déclaration multiple :
Une fonction peut être déclarée plusieurs fois dans le texte d'un programme,
mais les indications doivent concorder.
main :
La fonction principale main n'a pas besoin d'être déclarée.
Par définition, toutes les fonctions fournissent un résultat d'un
type que nous devons déclarer.
Une fonction peut renvoyer une valeur d'un type simple ou l'adresse d'une variable
ou d'un tableau.
Pour fournir un résultat en quittant une fonction, nous disposons de la commande
return.
Propriétés de la commande return
return
- évaluation de l'<Expression>
- conversion automatique du résultat de l'expression dans le type de la fonction
- renvoi du résultat
- terminaison de la fonction
La commande void
En C, il n'existe pas de structure spéciale pour la définition
de procédures comme en Pascal et en langage algorithmique.
Nous pouvons cependant employer une fonction du type void partout où
nous utiliserions une procédure en langage algorithmique ou en Pascal.
Remarque :
Si nous quittons une fonction (d'un type différent de void) sans renvoyer
de résultat à l'aide de return, la valeur transmise à la fonction appelante
est indéfinie.
Le résultat d'une telle action est imprévisible.
Si nous quittons une fonction (d'un type différent de void) sans renvoyer
de résultat à l'aide de return, la valeur transmise à la fonction appelante
est indéfinie. Le résultat d'une telle action est imprévisible.
La commande exit
Pour remédier à ce dilemme, nous pouvons utiliser la fonction
exit qui est définie dans la bibliothèque
exit nous permet d'interrompre l'exécution du programme en fournissant
un code d'erreur à l'environnement.
Pour pouvoir localiser l'erreur à l'intérieur du programme, il est avantageux
d'afficher un message d'erreur qui indique la nature de l'erreur et la fonction
dans laquelle elle s'est produite.
Exemple :
Fonction mathématique Tan :
#include
double TAN(double X)
{
if (cos(X) != 0)
return sin(X)/cos(X);
else
{
printf("\aFonction TAN: \n Erreur: Division par zéro ! \n");
exit(-1); /* Code erreur -1 */
}
}
Ignorer le résultat
Lors de l'appel d'une fonction, l'utilisateur est libre d'accepter le résultat d'une fonction ou de l'ignorer.
Exemple :
La fonction scanf renvoie le nombre de données correctement reçues comme
résultat.
Nous pouvons utiliser ce renseignement pour éviter un certain nombre
d'erreurs aux niveau de la saisie de donnees :
int JOUR, MOIS, ANNEE;
printf("Entrez la date actuelle : ");
do
{
printf("Entrez la date actuelle : ");
RES = scanf("%d %d %d", &JOUR,&MOIS,&ANNEE);
}
while (RES != 3);
5. Paramètres d'une fonction
Les paramètres ou arguments sont les "boîtes aux lettres"
d'une fonction.
Elles acceptent les données de l'extérieur et déterminent les actions et le
résultat de la fonction.
Techniquement, nous pouvons résumer le rôle des paramètres en C de la façon
suivante : les paramètres d'une fonction sont simplement des variables locales
qui sont initialisées par les valeurs obtenues lors de l'appel.
Conversion automatique
Lors d'un appel, le nombre et l'ordre des paramètres doivent nécessairement
correspondre aux indications de la déclaration de la fonction.
Les paramètres sont automatiquement convertis dans les types de la déclaration
avant d'être passés à la fonction.
Exemple ;
Le prototype de la fonction pow (bibliothèque
void
Evidemment, il existe aussi des fonctions qui fournissent leurs
résultats ou exécutent une action sans avoir besoin de données.
La liste des paramètres contient alors la déclaration void ou elle reste
vide.
5b. Passage des paramètres par valeur
En C, le passage des paramètres se fait toujours par la valeur
: les fonctions n'obtiennent que les valeurs de leurs paramètres et n'ont pas
d'accès aux variables elles-mêmes.
Les paramètres d'une fonction sont à considérer comme des variables locales
qui sont initialisées automatiquement par les valeurs indiquées lors d'un appel.
A l'intérieur de la fonction, nous pouvons donc changer les valeurs des paramètres
sans influencer les valeurs originales dans les fonctions appelantes.
Avantages
Le passage par valeur a l'avantage que nous pouvons utiliser les
paramètres comme des variables locales bien initialisées.
De cette façon, nous avons besoin de moins de variables d'aide.
5c. Passage de l'adresse d'une variable
Comme nous l'avons constaté ci-dessus, une fonction n'obtient
que les valeurs de ses paramètres.
Pour changer la valeur d'une variable de la fonction appelante, nous allons
procéder comme suit:
- la fonction appelante doit fournir l'adresse de la variable
- la fonction appelée doit déclarer le paramètre comme pointeur
On peut alors atteindre la variable à l'aide du pointeur.
Discussion d'un exemple
Nous voulons écrire une fonction PERMUTER qui échange le contenu
de deux variables du type int.
En première approche, nous écrivons la fonction suivante :
void PERMUTER (int A, int B)
{
int AIDE;
AIDE = A;
A = B;
B = AIDE;
}
Si nous appelons cette fonction de la facon suivante : PERMUTER(X
, Y) ;
... il ne se passe rien...
Explication :
Lors de l'appel, les valeurs de X et de Y sont copiées dans les paramètres A
et B.
PERMUTER échange bien contenu des variables locales A et B, mais les valeurs
de X et Y restent les mêmes.
Pour pouvoir modifier le contenu de X et de Y, la fonction PERMUTER
a besoin des adresses de X et Y.
En utilisant des pointeurs, nous écrivons une deuxième fonction :
void PERMUTER (int *A, int *B)
{
int AIDE;
AIDE = *A;
*A = *B;
*B = AIDE;
}
Nous appelons alors la fonction pa r: PERMUTER(&X, &Y);
Le contenu des variables X et Y est échangé !
Explication : Lors de l'appel, les adresses de X et de Y sont
copiées dans les pointeurs A et B.
PERMUTER échange ensuite le contenu des adresses indiquées par les pointeurs
A et B.
5d. Passage de l'adresse d'un tableau à une dimension
Méthode
Comme il est impossible de passer "la valeur" de tout
un tableau à une fonction, on fournit l'adresse d'un élément du tableau.
En général, on fournit l'adresse du premier élément du tableau, qui est donnée
par le nom du tableau.
Déclaration
Dans la liste des paramètres d'une fonction, on peut déclarer
un tableau par le nom suivi de crochets :
<Type> <NomTableau>[]
ou simplement par un pointeur sur le type des éléments du tableau
:
<Type> *<Pointeur>
Exemple :
La fonction strlen calcule et retourne la longueur d'une chaîne de caractères
fournie comme paramètre:
int strlen(char *S)
{
int N;
for (N=0; *S != "\0"; S++)
N++;
return N;
}
A la place de la déclaration de la chaîne comme char *S, on aurait aussi pu indiquer char S[].
Appel
Lors d'un appel, l'adresse d'un tableau peut être donnée par le nom du tableau, par un pointeur ou par l'adresse d'un élément quelconque du tableau.
Exemple
Après les instructions
char CH[] = "Bonjour !";
char *P;
P = CH;
nous pouvons appeler la fonction strlen définie ci-dessus par :
strlen(CH) /* résultat: 9 */
strlen(P) /* résultat: 9 */
strlen(&CH[4]) /* résultat: 5 */
strlen(P+2) /* résultat: 7 */
strlen(CH+2) /* résultat: 7 */
Dans les trois dernièrs appels, nous voyons qu'il est possible de fournir une
partie d'un tableau à une fonction, en utilisant l'adresse d'un élément à l'intérieur
de tableau comme paramètre.
5e. Passage de l'adresse d'un tableau à deux dimension
Exemple
Imaginons que nous voulons écrire une fonction qui calcule la somme de tous les éléments d'une matrice de réels A dont nous fournissons les deux dimensions N et M comme paramètres.
Problème
Comment pouvons-nous passer l'adresse de la matrice à la fonction ?
Par analogie avec ce que nous avons vu au chapitre précédent,
nous pourrions envisager de déclarer le tableau concerné dans l'en-tête de la
fonction sous la forme A[][].
Dans le cas d'un tableau à deux dimensions, cette méthode ne fournit pas assez
de données, parce que le compilateur a besoin de la deuxième dimension du tableau
pour déterminer l'adresse d'un élément A[i][j].
Une solution praticable consiste à faire en sorte que la fonction reçoive un pointeur (de type float*) sur le début de la matrice et de parcourir tous les éléments comme s'il s'agissait d'un tableau à une dimension N*M.
Cela nous conduit à cette fonction:
float SOMME(float *A, int N, int M)
{
int I;
float S;
for (I=0 ; I<N*M ; I++)
}
Lors d'un appel de cette fonction, la seule difficulté consiste
à transmettre l'adresse du début du tableau sous forme d'un pointeur sur float.
Prenons par exemple un tableau déclaré par :
float A[3][4];
Le nom A correspond à la bonne adresse, mais cette adresse est
du type "pointeur sur un tableau de 4 éléments du type float".
Si notre fonction est correctement déclarée, le compilateur la convertira automatiquement
dans une adresse du type "pointeur sur float".
Toutefois, comme nous l'avons déjà remarqué précédemment, on gagne
en lisibilité et on évite d'éventuels messages d'avertissement si on utilise
l'opérateur de conversion forcée.
Solution
Voici finalement un programme faisant appel à notre fonction SOMME:
#include
main()
{
/* Prototype de la fonction SOMME */
float SOMME(float *A, int N, int M);
/* Déclaration de la matrice */
float T[3][4] =
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9,10,11,12}
};
/* Appel de la fonction SOMME */
printf("Somme des éléments : %f \n", SOMME((float*)T, 3,
4) );
return 0;
}
Rappel :
Rappelons encore une fois que lors de l'interprétation d'un tableau à deux dimensions
comme tableau unidimensionnel, il faut calculer les adresses des composantes
à l'aide du nombre de colonnes maximal réservé lors de la déclaration.
6. Les modules en langage algorithmique, en Pascal et en C
Ce chapitre résume les différences principales entre les modules (programme principal, fonctions, procédures) dans les différents langages de programmation que nous connaissons.
En Pascal et en langage algorithmique, nous distinguons programme principal,
procédures et fonctions.
En C, il existe uniquement des fonctions.
La fonction principale main se distingue des autres fonctions par deux
qualités:
-Elle est exécutée lors de l'appel du programme
-Les types du résultat (int) et des paramètres (void) sont fixés.
Définition des modules
En langage algorithmique, le programme principal, les fonctions et les procédures
sont déclarés dans des blocs distincts.
Il est interdit d'imbriquer leurs définitions.
La définition du programme principal précède celle des fonctions et des procédures.
Exemple :
Programme P
...
FinProgramme
Fonction F1(...) : ...
...
FinFonction
Fonction F2(...) : ...
...
FinFonction
En Pascal, les définitions des modules peuvent être imbriquées.: on peut définir des fonctions et des procédures localement à l'intérieur d'autres fonctions ou procédures.
Exemple :
Program P
Function F1(...) : ...
Begin {F1}
...
End{F1};
Function F2(...) : ...
Begin {F2}
...
End{F2};
Begin {P}
...
End{P};
En C, il est interdit de définir des fonctions à l'intérieur d'autres fonctions, mais nous pouvons déclarer des fonctions localement.
Exemple :
main()
{
... F1(...);
...
}
... F1(...)
{
...F2(...);
...
}
... F2(...)
{
...
}
Variables locales
En Pascal et en langage algorithmique, nous pouvons déclarer des variables
locales au début des fonctions et des procédures.
En C, il est permis (mais déconseillé) de déclarer des variables locales au
début de chaque bloc d'instructions.
Variables globales
En Pascal et en langage algorithmique, les variables globales sont définies
au début du programme principal.
En C, les variables globales sont définies au début du fichier, à l'extérieur
de toutes les fonctions (les variables de la fonction principale main
sont locales à main.).
Passage des paramètres
En Pascal et en langage algorithmique, nous distinguons entre passage des paramètres
par valeur et passage des paramètres par référence.
En C, le passage des paramètres se fait toujours par la valeur.
Pour pouvoir changer le contenu d'une variable déclarée dans une autre fonction,
il faut utiliser un pointeur comme paramètre de passage et transmettre l'adresse
de la variable lors de l'appel.
Conclusion
Vu de plus près, les trois langages offrent les mêmes mécanismes pour le passage
des paramètres, mais :
-En C nous devons veiller nous-mêmes à opérer avec les adresses et les pointeurs
respectifs si nous voulons changer le contenu d'une variable déclarée dans une
autre fonction
-en langage algorithmique et en Pascal, les mêmes opérations se déroulent derrière
les rideaux, sous l'étiquette "passage par référence".
7. Pointeurs sur des fonctions
Les deux seules opérations qui peuvent être effectuées sur une fonction sont
l'appeler et en prendre l'adresse.
Exemple :
void Texte(char *T) /* on définit une fonction... */
{
printf(T) ;
printf("\n");
}
void (*PtrF) (char *); /* ...ainsi qu'une variable, PtrF , qui peut contenir
un pointeur sur elle */
/* L'adresse de la fonction est mise dans la variable et la fonction est appelée
*/
PtrF = &Texte ;
(*PtrF)("Bonjour");
/* Autre syntaxe, mais même signification */
PtrF = Texte;
(PtrF)("Bonjour");