Opérateurs d'indirection et d'adresse

L’opérateur d’indirection unaire (*) accède à une valeur indirectement via un pointeur. L’opérande doit être un type de pointeur. Le résultat de l'opération est la valeur adressée par l'opérande ; autrement dit, la valeur à l'adresse vers laquelle son opérande pointe. Le type du résultat est le type traité par l'opérande.

Le résultat de l’opérateur d’indirection est type si l’opérande est de type pointeur-à-type. Si l'opérande pointe vers une fonction, le résultat est un désignateur de fonction. S’il pointe vers un objet, le résultat est une lvalue qui désigne l’objet.

Si la valeur de pointeur n’est pas valide, le résultat de l’opérateur d’indirection est non défini. Voici certaines des conditions les plus courantes qui invalident une valeur de pointeur :

  • Le pointeur est un pointeur null.

  • Le pointeur spécifie l’adresse d’un objet après la fin de sa durée de vie au moment de la référence. (Par exemple, un objet qui est sorti de l’étendue ou qui a été désalloué.)

  • Le pointeur spécifie une adresse alignée de façon inappropriée pour le type de l’objet désigné.

  • Le pointeur spécifie une adresse non utilisée par le programme en cours d'exécution.

L’opérateur address-of unaire (&) prend l’adresse de son opérande. L’opérande doit être l’un des éléments suivants :

  • lvalue qui désigne un objet qui n’est pas déclaré register et qui n’est pas un champ de bits.

  • Résultat d’un opérateur de déréférencement unaire (*) ou de déréférencement de tableau ([]).

  • Désignateur de fonction.

Le résultat est de type pointeur vers operand_type pour un opérande de type operand_type.

Si l’opérande est le résultat d’un opérateur * unaire, aucun opérateur n’est évalué et le résultat est comme si les deux étaient omis. Le résultat n’est pas une lvalue et les contraintes sur les opérateurs s’appliquent toujours. Si l’opérande est le résultat d’un opérateur [], l’opérateur & et l’opérateur * unaire impliqué par l’opérateur [] ne sont pas évalués. Le résultat a le même effet que la suppression de l’opérateur & et la modification de l’opérateur [] en opérateur +. Sinon, le résultat est un pointeur vers l’objet ou la fonction désignée par l’opérande.

Exemples

Les exemples ci-dessous utilisent ces déclarations courantes :

int *pa, x;
int a[20];

Cette déclaration utilise l’opérateur address-of (&) pour prendre l’adresse du sixième élément du tableau a. Le résultat est stocké dans la variable pointeur pa :

pa = &a[5];

L'opérateur d'indirection (*) est utilisé dans cet exemple pour accéder à la valeur int, à l'adresse stockée dans pa. La valeur est assignée à la variable de type entier x :

x = *pa;

Cet exemple montre que le résultat de l’application de l’opérateur d’indirection à l’adresse de x équivaut à x :

assert( x == *&x );

Cet exemple montre des moyens équivalents de déclarer un pointeur vers une fonction :

int roundup( void );     /* Function declaration */

int  *proundup  = roundup;
int  *pround  = &roundup;
assert( pround == proundup );

Une fois que la fonction roundup est déclarée, deux pointeurs désignant roundup sont déclarés et initialisés. Le premier pointeur, proundup, est initialisé en utilisant uniquement le nom de la fonction, tandis que le second, pround, utilise l'opérateur d'adresse dans l'initialisation. Les initialisations sont équivalentes.

Voir aussi

Opérateur d’indirection : *
Opérateur d’adresse : &