• Aucun résultat trouvé

Une autre façon d'envoyer un pointeur à une fonction

Dans le document Apprenez à programmer en C ! (Page 120-124)

void triplePointeur(int *pointeurSurNombre) {

*pointeurSurNombre *= 3; // On multiplie par 3 la valeur de nombre

}

Code : Console 15

La fonction triplePointeur prend un paramètre de type int* (c'est-à-dire un pointeur sur int). Voici ce qu'il se passe dans l'ordre, en partant du début du main :

1. une variable nombre est créée dans le main. On lui affecte la valeur 5. Ça, vous connaissez ;

2. on appelle la fonction triplePointeur. On lui envoie en paramètre l'adresse de notre variable nombre ; 3. la fonction triplePointeur reçoit cette adresse dans pointeurSurNombre. À l'intérieur de la fonction

triplePointeur, on a donc un pointeur pointeurSurNombre qui contient l'adresse de la variable nombre ; 4. maintenant qu'on a un pointeur sur nombre, on peut modifier directement la variable nombre en mémoire ! Il suffit

d'utiliser *pointeurSurNombre pour désigner la variable nombre ! Pour l'exemple, on fait un simple test : on multiplie la variable nombre par 3 ;

5. de retour dans la fonction main, notre nombre vaut maintenant 15 car la fonction triplePointeur a modifié directement la valeur de nombre.

Bien sûr, j'aurais pu faire un simple return comme on a appris à le faire dans le chapitre sur les fonctions. Mais l'intérêt, là, c'est que de cette manière, en utilisant des pointeurs, on peut modifier la valeur de plusieurs variables en mémoire (on peut donc « renvoyer plusieurs valeurs »). Nous ne sommes plus limités à une seule valeur !

Quel est l'intérêt maintenant d'utiliser un return dans une fonction si on peut se servir des pointeurs pour modifier des valeurs ?

Ça dépendra de vous et de votre programme. C'est à vous de décider. Il faut savoir que les return sont bel et bien toujours utilisés en C. Le plus souvent, on s'en sert pour renvoyer ce qu'on appelle un code d'erreur : la fonction renvoie 1 (vrai) si tout s'est bien passé, et 0 (faux) s'il y a eu une erreur pendant le déroulement de la fonction.

Une autre façon d'envoyer un pointeur à une fonction

Dans le code source qu'on vient de voir, il n'y avait pas de pointeur dans la fonction main. Juste une variable nombre. Le seul pointeur qu'il y avait vraiment était dans la fonction triplePointeur (de type int*).

Il faut absolument que vous sachiez qu'il y a une autre façon d'écrire le code précédent, en ajoutant un pointeur dans la fonction main :

Code : C

void triplePointeur(int *pointeurSurNombre);

int main(int argc, char *argv[]) { int nombre = 5;

int *pointeur = &nombre; // pointeur prend l'adresse de nombre triplePointeur(pointeur); // On envoie pointeur (l'adresse de nombre) à la fonction

printf("%d", *pointeur); // On affiche la valeur de nombre avec

*pointeur return 0;

}

void triplePointeur(int *pointeurSurNombre)

{ *pointeurSurNombre *= 3; // On multiplie par 3 la valeur de nombre

}

Comparez bien ce code source avec le précédent. Il y a de subtiles différences et pourtant le résultat est strictement le même : Code : Console

15

Ce qui compte, c'est d'envoyer l'adresse de la variable nombre à la fonction. Or, pointeur vaut l'adresse de la variable nombre, donc c'est bon de ce côté ! On le fait seulement d'une manière différente en créant un pointeur dans la fonction main.

Dans le printf (et c'est juste pour l'exercice), j'affiche le contenu de la variable nombre en tapant *pointeur. Notez qu'à la place, j'aurais pu écrire nombre : le résultat aurait été identique car *pointeur et nombre désignent la même chose dans la mémoire.

Dans le programme « Plus ou Moins », nous avons utilisé des pointeurs sans vraiment le savoir. C'était en fait en appelant la fonction scanf. En effet, cette fonction a pour rôle de lire ce que l'utilisateur a entré au clavier et de renvoyer le résultat. Pour que la fonction puisse modifier directement le contenu de votre variable afin d'y placer la valeur tapée au clavier, elle a besoin de l'adresse de la variable :

Code : C

int nombre = 0;

scanf("%d", &nombre);

La fonction travaille avec un pointeur sur la variable nombre et peut ainsi modifier directement le contenu de nombre.

Comme on vient de le voir, on pourrait créer un pointeur qu'on enverrait à la fonction scanf : Code : C

int nombre = 0;

int *pointeur = &nombre;

scanf("%d", pointeur);

Attention à ne pas mettre le symbole & devant pointeur dans la fonction scanf ! Ici, pointeur contient lui-même l'adresse de la variable nombre, pas besoin de mettre un & ! Si vous faisiez ça, vous enverriez l'adresse où se trouve le pointeur : or c'est de l'adresse de nombre dont on a besoin.

Qui a dit : "Un problème bien ennuyeux" ?

Le chapitre est sur le point de s'achever, il est temps de retrouver notre fil rouge. Si vous avez compris ce chapitre, vous devriez être capables de résoudre le problème, maintenant. Qu'est-ce que vous en dites ? Essayez !

Voici la solution pour comparer : Code : C decoupeMinutes(&heures, &minutes);

// Cette fois, les valeurs ont été modifiées ! printf("%d heures et %d minutes", heures, minutes);

return 0;

}

void decoupeMinutes(int* pointeurHeures, int* pointeurMinutes) { /* Attention à ne pas oublier de mettre une étoile devant le nomdes pointeurs ! Comme ça, vous pouvez modifier la valeur des variables,

et non leur adresse ! Vous ne voudriez pas diviser des adresses, n'est-ce pas ? ;o) */

*pointeurHeures = *pointeurMinutes / 60;

*pointeurMinutes = *pointeurMinutes % 60;

}

Résultat :

Code : Console

1 heures et 30 minutes

Rien ne devrait vous surprendre dans ce code source. Toutefois, comme on n'est jamais trop prudent, je vais râbacher une fois de plus ce qui se passe dans ce code afin d'être certain que tout le monde me suit bien. C'est un chapitre important, vous devez faire beaucoup d'efforts pour comprendre : je peux donc bien en faire moi aussi pour vous !

1. Les variables heures et minutes sont créées dans le main.

2. On envoie à la fonction decoupeMinutes l'adresse de heures et minutes.

3. La fonction decoupeMinutes récupère ces adresses dans des pointeurs appelés pointeurHeures et

pointeurMinutes. Notez que là encore, le nom importe peu. J'aurais pu les appeler h et m, ou même encore heures et minutes. Je ne l'ai pas fait car je ne veux pas que vous risquiez de confondre avec les variables heures et

minutes du main, qui ne sont pas les mêmes.

4. La fonction decoupeMinutes modifie directement les valeurs des variables heures et minutes en mémoire car elle possède leurs adresses dans des pointeurs. La seule contrainte, un peu gênante je dois le reconnaître, c'est qu'il faut impérativement mettre une étoile devant le nom des pointeurs si on veut modifier la valeur de heures et de minutes.

Si on n'avait pas fait ça, on aurait modifié l'adresse contenue dans les pointeurs, ce qui n'aurait servi… à rien.

De nombreux lecteurs m'ont fait remarquer qu'il était possible de résoudre le « problème » sans utiliser de pointeurs.

Oui, bien sûr c'est possible, mais il faut contourner certaines règles que nous nous sommes fixées : on peut utiliser des variables globales (mais on l'a dit, c'est mal), ou encore faire un printf dans la fonction decoupeMinutes (alors que c'est dans le main qu'on veut faire le printf !). L'exercice est un peu scolaire et peut donc être contourné si vous êtes malins, ce qui vous fait peut-être douter de l'intérêt des pointeurs. Soyez assurés que cet intérêt vous paraîtra de plus en plus évident au cours des chapitres suivants.

En résumé

Chaque variable est stockée à une adresse précise en mémoire.

Les pointeurs sont semblables aux variables, à ceci près qu'au lieu de stocker un nombre ils stockent l'adresse à laquelle se trouve une variable en mémoire.

Si on place un symbole & devant un nom de variable, on obtient son adresse au lieu de sa valeur (ex. : &age).

Si on place un symbole * devant un nom de pointeur, on obtient la valeur de la variable stockée à l'adresse indiquée par le pointeur.

Les pointeurs constituent une notion essentielle du langage C, mais néanmoins un peu complexe au début. Il faut prendre le temps de bien comprendre comment ils fonctionnent car beaucoup d'autres notions sont basées dessus.

Dans le document Apprenez à programmer en C ! (Page 120-124)

Documents relatifs