Il y a deux méthodes pour passer des variables en paramètres dans une fonction : le passage par valeur ou le passage par variable. Ces méthodes sont décrites ci-dessous.
La valeur de l'expression passée en paramètre est copiée dans une variable locale. C'est cette variable qui est utilisée pour faire les calculs dans la fonction appelée.
Si l'expression passée en paramètre est une variable, son contenu est copié dans la variable locale. Aucune modification de la variable locale dans la fonction appelée ne modifie la variable passée en paramètre, parce que ces modifications ne s'appliquent qu'à une copie de cette dernière.
Le C ne permet de faire que des passages par valeur.
Exemple 3-4. Passage de paramètre par valeur
void test(int j) /* j est la copie de la valeur passée en
paramètre */
{
j=3; /* Modifie j, mais pas i. */
return;
}
int main(void)
{
int i=2;
test(i); /* Le contenu de i est copié dans j.
i n'est pas modifié. Il vaut toujours 2. */
test(2); /* La valeur 2 est copiée dans j. */
return 0;
}La deuxième technique consiste à passer non plus la valeur des variables comme paramètre, mais à passer les variables elles-mêmes. Il n'y a donc plus de copie, plus de variables locales. Toute modification du paramètre dans la fonction appelée entraîne la modification de la variable passée en paramètre.
Le C ne permet pas de faire ce type de passage de paramètres (le C++ le permet en revanche).
Exemple 3-5. Passage de paramètre par variable en Pascal
Var i : integer;
Procedure test(Var j : integer)
Begin
{La variable j est strictement égale
à la variable passée en paramètre.}
j:=2; {Ici, cette variable est modifiée.}
End;
Begin
i:=3; {Initialise i à 3}
test(i); {Appelle la fonction. La variable i est passée en
paramètres, pas sa valeur. Elle est modifiée par
la fonction test.}
{Ici, i vaut 2.}
End.Puisque la fonction attend une variable en paramètre, on ne peut plus appeler test avec une valeur (test(3) est maintenant interdit, car 3 n'est pas une variable : on ne peut pas le modifier).
Les passages par valeurs permettent d'éviter de détruire par mégarde les variables passées en paramètre.
Les passages par variables sont plus rapides et plus économes en mémoire que les passages par valeur, puisque les étapes de la création de la variable locale et la copie de la valeur ne sont pas faites. Il faut donc éviter les passages par valeur dans les cas d'appels récursifs de fonction ou de fonctions travaillant avec des grandes structures de données (matrices par exemple).
Il n'y a qu'une solution : passer l'adresse de la variable. Cela constitue donc une application des pointeurs.
Voici comment l'exemple Exemple 3-5 serait programmé en C :
Exemple 3-6. Passage de paramètre par variable en C
void test(int *pj) /* test attend l'adresse d'un entier... */
{
*pj=2; /* ... pour le modifier. */
return;
}
int main(void)
{
int i=3;
test(&i); /* On passe l'adresse de i en paramètre. */
/* Ici, i vaut 2. */
return 0;
}À présent, il est facile de comprendre la signification de & dans l'appel de scanf : les variables à entrer sont passées par variable.
La solution du C est exactement la même que celle du Pascal du point de vue sémantique. En fait, le Pascal procède exactement de la même manière en interne, mais la manipulation des pointeurs est masquée par le langage. Cependant, plusieurs problèmes se posent au niveau syntaxique :
la syntaxe est lourde dans la fonction, à cause de l'emploi de l'opérateur * devant les paramètres ;
la syntaxe est dangereuse lors de l'appel de la fonction, puisqu'il faut systématiquement penser à utiliser l'opérateur & devant les paramètres. Un oubli devant une variable de type entier et la valeur de l'entier est utilisée à la place de son adresse dans la fonction appelée (plantage assuré, essayez avec scanf).
Le C++ permet de résoudre tous ces problème à l'aide des références. Au lieu de passer les adresses des variables, il suffit de passer les variables elles-mêmes en utilisant des paramètres sous la forme de références. La syntaxe des paramètres devient alors :
type &identificateur [, type &identificateur [...]]
Exemple 3-7. Passage de paramètre par référence en C++
void test(int &i) // i est une référence du paramètre constant.
{
i = 2; // Modifie le paramètre passé en référence.
return;
}
int main(void)
{
int i=3;
test(i);
// Après l'appel de test, i vaut 2.
// L'opérateur & n'est pas nécessaire pour appeler
// test.
return 0;
}| Précédent | Sommaire | Suivant |
| Lien entre les pointeurs et les références | Niveau supérieur | Arithmétique des pointeurs |