Member access operators
Les opérateurs d'accès aux membres permettent d'accéder aux membres de leurs opérandes.
| Opérateur | Nom de l'opérateur | Exemple | Description |
|---|---|---|---|
| [ ] | indice de tableau | a [ b ] | accède au b -ième élément du tableau a |
| * | déréférencement de pointeur | * a | déréférence le pointeur a pour accéder à l'objet ou à la fonction qu'il référence |
| & | adresse de | & a | crée un pointeur qui référence l'objet ou la fonction a |
| . | accès membre | a. b | accède au membre b de la structure ou de l' union a |
| - > | accès membre via pointeur | a - > b | accède au membre b de la structure ou de l' union pointée par a |
Table des matières |
Indice
L'expression d'indice de tableau a la forme
expression-pointeur
[
expression-entier
]
|
(1) | ||||||||
expression-entier
[
expression-pointeur
]
|
(2) | ||||||||
où
| pointer-expression | - | une expression de type pointeur vers un objet complet |
| integer-expression | - | une expression de type entier |
L'expression de l'opérateur d'indice est une expression lvalue dont le type est le type de l'objet pointé par pointer-expression .
Par définition, l'opérateur de subscript E1 [ E2 ] est exactement identique à * ( ( E1 ) + ( E2 ) ) . Si pointer-expression est une expression de tableau, elle subit une conversion lvalue-to-rvalue et devient un pointeur vers le premier élément du tableau.
En raison de la définition de l'addition entre un pointeur et un entier , le résultat est l'élément du tableau dont l'indice est égal au résultat de integer-expression (ou, si pointer-expression pointait vers le i-ème élément d'un tableau, l'indice du résultat est i plus le résultat de integer-expression )
Note : voir array pour les détails sur les tableaux multidimensionnels.
#include <stdio.h> int main(void) { int a[3] = {1,2,3}; printf("%d %d\n", a[2], // n == 3 2[a]); // same, n == 3 a[2] = 7; // subscripts are lvalues int n[2][3] = {{1,2,3},{4,5,6}}; int (*p)[3] = &n[1]; // elements of n are arrays printf("%d %d %d\n", (*p)[0], p[0][1], p[0][2]); // access n[1][] via p int x = n[1][2]; // applying [] again to the array n[1] printf("%d\n", x); printf("%c %c\n", "abc"[2], 2["abc"]); // string literals are arrays too }
Sortie :
3 3 4 5 6 6 c c
Déférencement
L'expression de déréférencement ou indirection a la forme
*
expression-pointeur
|
|||||||||
où
| pointer-expression | - | une expression de tout type pointeur |
Si pointer-expression est un pointeur vers une fonction, le résultat de l'opérateur de déréférencement est un désignateur de fonction pour cette fonction.
Si pointer-expression est un pointeur vers un objet, le résultat est une expression lvalue qui désigne l'objet pointé.
Le déréférencement d'un pointeur nul, d'un pointeur vers un objet en dehors de sa durée de vie (un pointeur pendulaire), d'un pointeur non aligné, ou d'un pointeur avec une valeur indéterminée est un comportement indéfini, sauf lorsque l'opérateur de déréférencement est annulé en appliquant l'opérateur d'adressage à son résultat, comme dans & * E .
Sortie :
*p = 1 *p = 7
Adresse de
L'expression d'adressage a la forme
&
fonction
|
(1) | ||||||||
&
expression-lvalue
|
(2) | ||||||||
&
*
expression
|
(3) | ||||||||
&
expression
[
expression
]
|
(4) | ||||||||
&
et
*
s'annulent mutuellement, aucun des deux n'est évalué
&
et le
*
qui est implicite dans
[]
s'annulent mutuellement, seule l'addition implicite dans
[]
est évaluée.
où
| lvalue-expression | - | une lvalue expression de tout type qui n'est pas un bit-field et n'a pas la classe de stockage register |
L'opérateur d'adresse produit l'adresse non-lvalue de son opérande, appropriée pour initialiser un pointeur vers le type de l'opérande. Si l'opérande est un désignateur de fonction (1) , le résultat est un pointeur vers fonction. Si l'opérande est un objet (2) , le résultat est un pointeur vers objet.
Si l'opérande est l'opérateur de déréférencement, aucune action n'est entreprise (il est donc acceptable d'appliquer &* à un pointeur nul), sauf que le résultat n'est pas une lvalue.
Si l'opérande est une expression d'index de tableau, aucune action n'est entreprise hormis la conversion tableau-vers-pointeur et l'addition, donc &a[N] est valide pour un tableau de taille N (obtenir un pointeur juste après la fin est autorisé, le déréférencer ne l'est pas, mais le déréférencement s'annule dans cette expression).
int f(char c) { return c;} int main(void) { int n = 1; int *p = &n; // adresse de l'objet n int (*fp)(char) = &f; // adresse de la fonction f int a[3] = {1,2,3}; int *beg=a, *end=&a[3]; // identique à end = a+3 }
Accès aux membres
L'expression d'accès aux membres a la forme
expression
.
nom-membre
|
|||||||||
où
| expression | - | une expression de type struct ou union |
| member-name | - | un identifiant qui nomme un membre de la structure ou de l'union désignée par expression |
L'expression d'accès membre désigne le membre nommé de la struct ou de l' union désigné par son opérande gauche. Elle a la même catégorie de valeur que son opérande gauche.
Si l'opérande gauche est qualifié const ou volatile , le résultat est également qualifié. Si l'opérande gauche est atomic , le comportement est indéfini.
Note : outre les identifiants qui nomment des objets de type struct ou union, les expressions suivantes peuvent avoir des types struct ou union : assignment , function call , comma operator , conditional operator , et compound literal .
#include <stdio.h> struct s {int x;}; struct s f(void) { return (struct s){1}; } int main(void) { struct s s; s.x = 1; // ok, modifie le membre de s int n = f().x; // f() est une expression de type struct s // f().x = 1; // Erreur : cette expression d'accès membre n'est pas une lvalue const struct s sc; // sc.x = 3; // Erreur : sc.x est const, ne peut pas être assigné union { int x; double d; } u = {1}; u.d = 0.1; // modifie le membre actif de l'union }
Accès aux membres via un pointeur
L'expression d'accès aux membres a la forme
expression
->
nom-membre
|
|||||||||
où
| expression | - | une expression de type pointeur vers struct ou union |
| member-name | - | un identifiant qui nomme un membre de la struct ou union pointé par expression |
L'expression d'accès au membre via un pointeur désigne le membre nommé du struct ou union pointé par son opérande gauche. Sa catégorie de valeur est toujours lvalue
Si le type pointé par l'opérande gauche est const ou volatile qualifié, le résultat est également qualifié. Si le type pointé par l'opérande gauche est atomic , le comportement est indéfini.
#include <stdio.h> struct s {int x;}; int main(void) { struct s s={1}, *p = &s; p->x = 7; // modifie la valeur de s.x via le pointeur printf("%d\n", p->x); // affiche 7 }
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C publiées antérieurement.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| DR 076 | C89 |
l'indirection superflue ne pouvait pas être annulée par
&
|
rendue annulable |
Références
- Norme C17 (ISO/CEI 9899:2018) :
-
- 6.5.2.1 Indiçage de tableau (p: 57-58)
-
- 6.5.2.3 Membres de structure et d'union (p: 58-59)
-
- 6.5.3.2 Opérateurs d'adresse et d'indirection (p: 59-61)
- Norme C11 (ISO/IEC 9899:2011) :
-
- 6.5.2.1 Indiçage de tableau (p: 80)
-
- 6.5.2.3 Membres de structure et d'union (p: 82-84)
-
- 6.5.3.2 Opérateurs d'adresse et d'indirection (p: 88-89)
- Norme C99 (ISO/CEI 9899:1999) :
-
- 6.5.2.1 Indiçage de tableau (p: 70)
-
- 6.5.2.3 Membres de structure et d'union (p: 72-74)
-
- 6.5.3.2 Opérateurs d'adresse et d'indirection (p: 78-79)
- Norme C89/C90 (ISO/CEI 9899:1990) :
-
- 3.3.2.1 Indiçage de tableau
-
- 3.3.2.3 Membres de structure et d'union
-
- 3.3.3.2 Opérateurs d'adresse et d'indirection
Voir aussi
| Opérateurs courants | ||||||
|---|---|---|---|---|---|---|
| affectation |
incrémentation
décrémentation |
arithmétique | logique | comparaison |
accès membre
accès |
autres |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
Documentation C++
pour
Opérateurs d'accès aux membres
|