&
E est de type
pointeur de t. Notons la simplification suivante : &*p en
p, si p est d'un type pointeur.
Cette opération est essentielle pour simuler le passage des arguments par référence et utile dans quelques autres cas. Tout abus est nocif.
Les opérations * et &
permettent d'expliquer le
fonctionnement de l'appel par référence en C.
Si n est une variable (ou plus généralement une expression
qu'on peut placer à gauche d'une affectation) que l'on veut faire
modifier par une fonction f, on passe à f en argument
l'adresse &
n de n. On doit donc déclarer
void f(int *p) { ... }
et appeler f(&n)
. Comme pour tout autre type, le passage de
l'argument &n
se fait par valeur, ce qui fait que l'adresse a
de n est copiée dans p. Dans le corps de la fonction,
à chaque fois que *p est lue ou écrite, c'est donc la variable
d'adresse a qui est lue ou écrite, c'est-à-dire n.
Par contre, si le corps de la fonction modifiait p, en lui affectant une autre valeur que a, p pointerait alors vers une autre variable que n, ce qui n'aurait pas l'effet attendu (ni sur n ni sur l'autre variable en question):
int m = 2, n = 3;
void f(int *p) {
p = &m;
*p = 4;
}
L'appel f(&n)
modifie la valeur de la variable m et non
celle de la variable n. Pour éviter ce risque, on devrait
déclarer
void f(int *const p);
ce qui permettrait au compilateur de détecter une affectation p = .... On peut lire int *const p comme int* (const p), ce qui exprime que la constante p est un pointeur.
D'autre part, si un passage par référence est souhaité seulement pour des raisons d'efficacité, pour éviter la copie d'un objet de grande taille (ce sera le cas notamment pour certains gros struct), on doit déclarer également la fonction avec un const, mais dans une autre position :
void f(const int *p);
Ici, const int *p se lit comme (const int) *p qui exprime que *p est un entier constant. Il est rare dans ce dernier cas que l'on souhaite que p soit modifié par la fonction ; on a donc tout intérêt à déclarer
void f(const int *const p);
pour faire vérifier par le compilateur que ni p ni *p ne sont modifiés.