Namespaces
Variants

Member access operators

From cppreference.net

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)

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

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 .

#include <stdio.h>
int main(void)
{
    int n = 1;
    int* p = &n;
    printf("*p = %d\n", *p); // la valeur de *p est ce qui est stocké dans n
    *p = 7; // *p est une lvalue
    printf("*p = %d\n", *p);
}

Sortie :

*p = 1
*p = 7

Adresse de

L'expression d'adressage a la forme

& fonction (1)
& expression-lvalue (2)
& * expression (3)
& expression [ expression ] (4)
1) adresse d'une fonction
2) adresse d'un objet
3) cas particulier : & et * s'annulent mutuellement, aucun des deux n'est évalué
4) cas particulier : & et le * qui est implicite dans [] s'annulent mutuellement, seule l'addition implicite dans [] est évaluée.

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

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

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 + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b

a [ b ]
* a
& a
a - > b
a. b

a ( ... )
a, b
( type ) a
a ? b : c
sizeof


_Alignof
(depuis C11)
(jusqu'à C23)

alignof
(depuis C23)

Documentation C++ pour Opérateurs d'accès aux membres