Il est tout à fait possible de modifier un pointeur, cest-à-dire de changer ladresse à laquelle il réfère. On dispose même pour cela dun certain nombre dopérateurs.
Lopérateur dincrémentation ++
par exemple agit de la même façon que sur des entiers. Cependant, p est augmenté dune position, non dun octet. En effet, p pointe sur un type T
qui a une certaine taille en octets t (dans le cas de int
par exemple, t vaut 2 ou 4 en général) ; lorsquon écrit p++
, dans ce cas, ladresse qui est la valeur de p est augmentée de t octets, afin de pointer sur lélément de type T
supposé suivre dans la mémoire.
On retrouve ainsi un comportement identique à celui des tableaux. Un pointeur de type int*
, par exemple, considère que la mémoire est découpée en tranches de deux octets (si le type int
occupe deux octets) ; un pointeur de type long*
la considère comme découpée en tranches de quatre octets, et un de type char*
la voit en tranches de un octet seulement.
Ainsi, si lon écrit :
char *pc; int *pi = (int*) pc; long *pl = (long*) pc; pc++; pi++; pl++;
et quau début pc
vaut 1000 par exemple, à la fin pc
vaudra 1001, pi
vaudra 1002, pl
vaudra 1004.
Exercice 3.3 |
Daprès les règles de précédence des opérateurs, quest-ce qui est affiché ici : char s[] = "verte", *p = s; cout << *++p; cout << ++*p; cout << *(p++); cout << *p++; |
Voir solution |
On peut ainsi ajouter ou retrancher un entier à un pointeur ; le pointeur se déplace alors du nombre de positions indiquées. Ainsi, en exécutant à la suite des précédentes :
pl += 6; pi -= 2;
le pointeur pl
pointera six positions dentiers longs plus loin, soit à ladresse 1004 + 6 * 4 = 1028, tandis que pi
pointera sur 1002 - 2 * 2 = 998.
Évidemment, il est aussi possible dajouter un entier à un pointeur, puis de placer le résultat dans un autre pointeur de même type :
pi2 = pi + 5;
Dans ce cas, comme pi
vaut 998, pi2
vaudrait 1008.
De même, il est possible de retrancher deux pointeurs de même type ; dans ce cas, on obtient un entier, qui nest pas la différence des adresses, mais la différence des positions. Par exemple la différence :
int i = pi2 - pi;
placera la valeur (1008 - 998)/2, soit 5, dans i
.
Il en résulte en particulier quon ne peut calculer la différence de deux pointeurs de types différents, sauf en utilisant une conversion de type afin de les faire coïncider :
i = pl - pi; // interdit types différents i = (int*) pl -pi; // ok, changement de type pour pl
Larithmétique des pointeurs est très souvent utilisée dans la pratique. Voici par exemple une implantation possible de la fonction strlen
qui renvoie la longueur dune chaîne de caractères (caractère nul final non compris) :
unsigned strlen(char *chaine) { for (char *s = chaine; *s; s++) // les chaînes se terminent par 0; return s -chaine; }
Que se passe-t-il en réalité ? Un autre pointeur char*
nommé s est créé et initialisé à la même valeur que chaine. Puis il est incrémenté (s++
), jusquà rencontrer le caractère nul (cest-à-dire jusquà ce quon nait plus *s != 0
, doù la forme particulièrement simple du test : *s
). La différence de valeur entre les deux pointeurs est alors égale à la longueur de la chaîne.
Exercice 3.4 |
Quelles modifications faudrait-il faire à la fonction précédente, si lon voulait trouver le nombre déléments non nuls consécutifs dans une table dentiers désignée par un pointeur |
Voir solution |
Exercice 3.5 |
En vous inspirant du schéma de fonction précédent, réécrivez la fonction On supposera les caractères |
Voir solution |
Précédent | Sommaire | Suivant |