Langage C – Pointeurs
Les pointeurs permettent de transmettre d’une manière plus efficace les données que traditionnellement.
Mais d’abord, qu’est-ce qu’un pointeur ?
Un pointeur est tout simplement une variable qui stocke l’adresse d’une autre donnée dans la mémoire de l’ordinateur.
La taille occupée par un pointeur est donc très petite : 2 octets sur les plateformes 16 bits, 3 octets pour
les systèmes 32 bits.
Les opérations sur les pointeurs sont donc très rapide et peu gourmandes en ressources système, ce qui permet
de réaliser des opérations très puissantes, irréalisables autrement, comme l’utilisation des listes chainées.
C’est en raison de ces quelques points que la syntaxe des pointeurs peu apparaitre un peu hermetique et complexe
au premier abord. Mais avec de la pratique, on se rend compte que ce n’est peut-être pas si compliqué que ça …
La mémoire
La mémoire d’un ordinateur est décomposée en 216 segments, c’est à dire 65536 segments. Lors
de l’execution, un programme est chargé dans l’un de ces 65536 segments.
Ce n’est pas tout. Chaque « morceau » de segment est reperé par une adresse, ou offset.
Le contenu d’une variable est donc stockée en mémoire et reperé par un segment et un offset.
Pour obtenir l’adresse d’une variable, on utilise l’opérateur & (et commercial, ou esperluette) devant le
nom de la variable.
L’exemple suivant n’a aucun interet : il affiche simplement l’adresse d’une variable.
#include <stdio.h>
int main(){
int variable;
printf("L'adresse la variable est %u", &variable);
return 0;
}
L’adresse transmise en sortie est variable et est susceptible de changer entre deux execution du programme.
Syntaxe
On déclare un pointeur comme on le ferait pour une variable, mais on rajoute l’opérateur * (étoile)
devant son identificateur lors de la déclaration :
type *identificateur[=initialisation];
Le type utilisé doit être celui qui sera pointé par le pointeur (normal !). L’initialisation est facultative,
mais il est recommandé de toujours initialisé un pointeur avant toute utilisation.
En effet, si on ne prend pas cette précaution, le pointeur est suceptible de pointer sur un emplacement arbitraire
de la mémoire de l’ordinateur, ce qui peut avoir des effets terriblement désastreux si on y prend pas garde.
Pour accéder au contenu d’une variable (et non pas à son adresse !), on utilise encore l’opérateur * (étoile)
devant l’identificateur de la variable.
L’utilisation de l’indentificateur sans l’opérateur * permet d’acceder à l’adresse du pointeur,
comme le montre l’exemple suivant :
#include <stdio.h>
int main(){
int *pointeur;
*pointeur=500;/* initialisation du contenu */
printf("L'adresse du pointeur est %u\n", pointeur);
printf("Ca valeur est %i", *pointeur);
return 0;
}
Attention! L’initialisation d’une variable lors de sa déclaration initialise l’adresse et non le
contenu!
Maintenant, voyons une utilisation concréte des pointeurs. Nous allons faire pointer un pointeur vers une
variable :
#include <stdio.h>
int main(){
int variable = 500;
int *pointeur = &variable;/* pointeur pointe sur variable*/
printf("Avant\nvariable : %i\npointeur : %i\n", variable, *pointeur);
variable++;/* On incrémente 'variable'*/
/* variable == 501*/
printf("Après\nvariable : %i\npointeur : %i\n", variable, *pointeur);
return 0;
}
On constate que la valeur renvoyée par variable et par *pointeur est indentique.
C’est tout à fait normal, puisque l’emplacement de la mémoire utilisé est le même pour les deux variables.
Lorsque l’on ne se sert plus d’un pointeur, il suffit de lui affecter comme adresse la valeur NULL :
int *pointeur = NULL;/* pointeur ne pointe sur rien*/