Les pointeurs et la gestion des adresses
Nous y voici enfin

Préparez-vous à comprendre pas mal de choses d'un coup, ce chapitre sera beaucoup théorique mais c'est l'un des plus important!
Les pointeurs sont
partout en programmation. Absolument partout! Vous en avez même utilisé ,sans le savoir, dès le chapitre sur les flux d'entrées et de sortie
Le but de ce chapitre est donc de vous expliquer ce que sont les pointeurs, à quoi ils servent et surtout comment s'en servir
Les pointeurs, une histoire ... de mémoire
La mémoire vive:
Tout d'abord, redéfinnissons ensemble comment est présentée la mémoire vive et coment elle fonctionne.
Nous avons vu précedemment que la mémoire vive permettait de stocker des informations temporaires (les variables). Seulement, savez-vous comment l'odinateur sait où trouver chaque variable dans son immense mémoire vive? Non? Et bien nous allons le découvrir ici
Les adresses
Le fonctionnement de la mémoire vive est assez simple. Imaginez qu'une maison représente une variable, et que le monde entier représente la taille de mémoire vive. Vous avez vu le nombre de maison?! L'ordinateur ne pourrait jamais retrouver une variable (=maison) dans la mémoire (=le monde)! Mais heureusement, pour pallier ce problème on a inventé quelque chose de simple et d'efficace: les adresses.
C'est comme pour les maisons! Comment trouve-t-on une maison en particulier? Grâce à son adresse! Et bien comment retrouve-t-on où est stockée une variable dans la mémoire vive? Grâce à son adresse

Regardez ce schéma pour mieux comprendre à quoi ressemble la mémoire vive de votre ordinateur:

A gauche, ce sont les adresses (elles vont beaucoup plus loin que 5 025 453 158, il y en a un nombre immense

). Et à chaque adresse correspond un endroit de libre où l'on peut y stocker une variable. Attention, j'ai bien dis y stocker
une seule variable. Une variable n'étant qu'un chiffre (une lettre est aussi un chiffre et donc un mot, une suite de chiffre)
on ne peut stocker qu'un seul chiffre par emplacement mémoire.
Donc lorsque vous déclarez une variable, voici ce qui se passe en mémoire:
1) Le programme demande à l'ordinateur s'il peut prendre une partie de sa mémoire.
2) L'ordinateur accepte en lui indiquant l'adresse d'un emplacement mémoire qu'il pourra utiliser.
3) Le programme mémorise l'adresse.
Comprenez bien que les noms que vous donnez aux variables ne sont en réalité que des adresses. On a donné la possibilité de leur mettre des noms dans le code source juste afin de s'y retrouver
Du coup, lorsque vous aurez, dans la suite du programme, besoin de cette variable, le programme ira tout simplement à l'adresse indiquée
Se servir des adresses
Nous allons maintenant voir comment afficher l'adresse d'une variable
Pour cela, il faut tout d'abord ... créer une variable oui!

Allez on va prendre un int
int maVariable
= 10;
Pour afficher la valeur de la variable, nous faisons bien ceci:
printf
("%d", maVariable
);
Et bien pour afficher l'adresse d'une variable, il faut faire comme ceci:
printf
("%p", &maVariable
);
Le symbole "%p" a été spécialement concu pour les adresses, donc préférez le aux autres classique "%d", "%lf", etc.. qui fonctionnerons quand même

Voici ce que cela affiche chez moi:
Cette adresse est bein un nombre, mais écrit en format hexadécimal.
Notez qu'il est tout à fait normal que vous n'ayez pas la même adresse d'affichée que moi et ne vous étonnez pas non plus si elle change une fois le programme relancé! La raison est simple: nous n'avons pas la même quantité de mémoire vive ni la même utilisation de celle ci
Le symbole "&" devant la variable doit vous rappeler quelque chose. En effet, nous l'avons déjà utilisé avec scanf sans trop vous expliquer pourquoi

Il est maintenant temps de remédier à cela
Lorsque le signe "&" est présent devant une variable,
cela désigne l'adresse de cette variable et non sa valeur
Nous pouvons donc faire ceci pour mieux faire la différence:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int maVariable = 10;
printf("maVariable vaut %d et se situe a l'adresse %p de ma memoire vive.", maVariable, &maVariable);
return 0;
}
Ce qui nous donne:
Donc il suffit de se rappeler qu'il faut rajouter devant une variable le signe "&" pour donner son adresse.
Les pointeurs
Mais qu'est ce dont qu'un pointeur? Nous avons déjà vu de nombreux types de variables (int, char, double, float, etc...).
Et bien en fait, un pointeur n'est rien d'autre qu'une variable dans laquelle est stockée ... une adresse!

Et grâce à cela, on va pouvoir faire plein de zoli' choses
Voici comment créer un pointeur: Il suffit de rajouter, collé au nom de la variable une étoile "*" comme ceci:
int *monPointeur
= NULL
;
L'étoile signifie qu'il s'agit d'un pointeur. Le pointeur peut être de n'importe quel type
Enfin, on voit que le pointeur est initialisé à
NULL (en majuscules!). NULL permet de s'assurer que le pointeur ne contient
rien. Il est super-important d'initialiser une variable et d'autant plus un pointeur!
Etant donné qu'un pointeur est créé pour stocker l'adresse d'une variable voici comment lui affecter la valeur de maVariable. Tout simplement:
int maVariable
= 10;
int *monPointeur
= &maVariable
;
Explications:
On créer une variable valant 10. On créer ensuite un pointeur valant l'adresse de maVariable.
Du coup, si on affchiche la variable monPointeur (qui est donc un pointeur) comme une variable classique, il devrait afficher sa valeur et par conséquent ... l'adresse de maVariable!
Essayons:
#include <stdlib.h>
#include <stdio.h>
int main
()
{
int maVariable
= 10;
int *monPointeur
= NULL;
monPointeur
= &maVariable
;
printf
("monPointeur vaut %p et l'adresse de maVariable est %p", monPointeur
, &maVariable
);
return 0;
}
Ce qui donne bien:

On vient d'apprendre pas mal de chose là! Mais savez-vous que l'on peut faire encore plus fort?!
En effet, il est possible de gérer une variable grâce à une autre! Et tout cela encore grâce aux pointeurs!

Maintenant, ce que je vais vous expliquer est
la chose à retenir des pointeurs. Tenez-vous bien:
On peut, comme nous venons de le voir, créer un pointeur contenant l'adresse d'une variable. Mais l'on peut aussi accéder, grâce à ce pointeur, à la variable se trouvant à cette adresse et par conséquent, la modifier!
On dit que le pointeur "monPointeur" pointe sur la variable "maVaiable".
(vocabulaire à retenir).
Pour accéder, à partir d'un pointeur, à la variable que ce dernier pointe, il suffit de mettre l'étoile devant le pointeur.
Voici un exemple:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int maVariable = 10;
int *monPointeur = NULL;
monPointeur = &maVariable;
printf("maVariable vaut %d et monPointeur pointe sur une adresse memoire ou est stocke la valeur %d.", maVariable, *monPointeur);
return 0;
}
Ce qui fait apparaître à l'écran:
C'est magique! Nous pouvons accéder à une variable juste avec son adresse!
Voici un petit mémo de ce qu'il faut impérativement retenir:
maVariable --> désigne la valeur contenue dans cette variable.
&maVariable --> désigne l'adresse de cette variable.
monPointeur --> désigne la valeur contenue dans ce pointeur (c'est donc une adresse).
*monPointeur --> désigne la valeur de la variable pointée par le pointeur.
Si vous maitrisez cela, vous avez tout compris des pointeurs!

Sinon revoyez tout et faîtes des tests. J'ai personnelement mis beaucoup de temps à comprendre le fonctionnement des pointeurs en programmation
Passer un pointeur à une fonction
A partir de là, on va voir le vrai "plus" qu'apportent les pointeurs en programmation
Essayez tout d'abord ce code-ci:
#include <stdlib.h>
#include <stdio.h>
void fonctionIncrementation
(int maVariable
);
int main
()
{
int maVariable
= 39;
printf
("maVariable avant incrementation --> %d ", maVariable
);
fonctionIncrementation
(maVariable
);
printf
("maVariable apres incrementation --> %d", maVariable
);
return 0;
}
void fonctionIncrementation
(int maVariable
)
{
maVariable
+= 1;
}
Ce qui fait apparaître ceci:

Mais c'est bizarre! On donne "maVariable" à une fonction qui incrémente la variable et on trouve, à la fin, une nouvelle fois 39!? @_@
La raison en est très simple:
Lorsque vous envoyez une variable en argument à une fonction, celle-ci fait juste
une simple copie de cette variable et travaille sur cette copie! En fin de compte, la variable passée en argument n'est jamais modifiée par la fonction ce qui fait qu'elle ne change aucunement de valeur.
Mais maintenant que vous connaissez tous les petits secrets des pointeurs, laissez-moi vous en montrer un dernier: modifier une variable avec une fonction!
Voici le code qui fonctionne:
#include <stdlib.h>
#include <stdio.h>
void fonctionIncrementation
(int *maVariable
); //Prototype de la fonction.
int main
()
{
int maVariable
= 39; //On créer une variable qui vaut 39.
printf
("maVariable avant incrementation --> %d ", maVariable
); /*On affiche la variable et donc 39.*/
fonctionIncrementation
(&maVariable
); //On donne en argument l'adresse de la variable.
printf
("maVariable apres incrementation --> %d", maVariable
);
return 0;
}
//On stocke l'adresse donnée dans un pointeur nommé monPointeur.
void fonctionIncrementation
(int *monPointeur
)
{
*monPointeur
+= 1; //On ajoute 1 à la variable pointée par monPointeur.
}
J'espère que les commentaires rendant plus clair ce code
Il suffit "juste" de donner l'adresse de la variable à la fonction puis de modifier cette variable directement avec un pointeur. La variable est donc cette fois bien modifiée et n'est plus une simple copie.
De ce fait, vous pouvez même modifier directement plusieurs variables grâce à une fonction sans utiliser de
return!
Voilà un nouveau chapitre qui se termine. Un chapitre long mais très important! n'hésitez pas à poser des questions et à relire ce chapitre ainsi qu'à faire des tests!

Le prochain chapitre vous apprendra à créer vos propres types de variables!
Les chaines de caractères Les structures