Share via


Pointeurs const et volatile

Les mot clé const et volatiles changent la façon dont les pointeurs sont traités. La const mot clé spécifie que le pointeur ne peut pas être modifié après l’initialisation ; le pointeur est protégé contre la modification par la suite.

L’mot clé volatile spécifie que la valeur associée au nom qui suit peut être modifiée par des actions autres que celles de l’application utilisateur. Par conséquent, le volatile mot clé est utile pour déclarer des objets en mémoire partagée accessibles par plusieurs processus ou zones de données globales utilisées pour la communication avec des routines de service d’interruption.

Lorsqu’un nom est déclaré en tant que volatile, le compilateur recharge la valeur de la mémoire chaque fois qu’il est accessible par le programme. Cela réduit considérablement les optimisations possibles. Toutefois, lorsque l'état d'un objet peut changer de manière inattendue, c'est la seule façon de garantir des performances prévisibles du programme.

Pour déclarer l’objet pointé par le pointeur en tant que const ou volatile, utilisez une déclaration du formulaire :

const char *cpch;
volatile char *vpch;

Pour déclarer la valeur du pointeur ( autrement dit, l’adresse réelle stockée dans le pointeur) en tant que const ou volatile, utilisez une déclaration du formulaire :

char * const pchc;
char * volatile pchv;

Le langage C++ empêche les affectations qui autorisent la modification d’un objet ou d’un pointeur déclaré en tant que const. De telles assignations supprimeraient les informations avec lesquelles l'objet ou le pointeur a été déclaré, ce qui entraînerait la violation de l'objectif de la déclaration d'origine. Prenons les déclarations suivantes :

const char cch = 'A';
char ch = 'B';

Étant donné les déclarations précédentes de deux objets (cchde type const char et ch, de type char), les déclarations/initialisations suivantes sont valides :

const char *pch1 = &cch;
const char *const pch4 = &cch;
const char *pch5 = &ch;
char *pch6 = &ch;
char *const pch7 = &ch;
const char *const pch8 = &ch;

Les déclarations/initialisations suivantes sont erronées.

char *pch2 = &cch;   // Error
char *const pch3 = &cch;   // Error

La déclaration de pch2 déclare un pointeur par l'intermédiaire duquel un objet constant peut être modifié et par conséquent désactivé. La déclaration de pch3 spécifie que le pointeur est constant, et non l’objet ; la déclaration n’est pas autorisée pour la même raison que la pch2 déclaration n’est pas autorisée.

Les huit assignations suivantes indiquent l'assignation par l'intermédiaire du pointeur et la modification de la valeur du pointeur pour les déclarations précédentes ; pour le moment, supposons que l'initialisation est correcte de pch1 à pch8.

*pch1 = 'A';  // Error: object declared const
pch1 = &ch;   // OK: pointer not declared const
*pch2 = 'A';  // OK: normal pointer
pch2 = &ch;   // OK: normal pointer
*pch3 = 'A';  // OK: object not declared const
pch3 = &ch;   // Error: pointer declared const
*pch4 = 'A';  // Error: object declared const
pch4 = &ch;   // Error: pointer declared const

Les pointeurs déclarés comme , ou en tant que volatilemélange de const et volatile, obéissent aux mêmes règles.

Les pointeurs vers const des objets sont souvent utilisés dans les déclarations de fonction comme suit :

errno_t strcpy_s( char *strDestination, size_t numberOfElements, const char *strSource );

L’instruction précédente déclare une fonction, strcpy_s, où deux des trois arguments sont de type pointeur vers char. Étant donné que les arguments sont passés par référence et non par valeur, la fonction est libre de modifier les deux strDestination et strSource si strSource elles n’ont pas été déclarées comme const. La déclaration de strSource tel const garantit que l’appelant ne strSource peut pas être modifié par la fonction appelée.

Remarque

Étant donné qu’il existe une conversion standard de typename* enconst typename*, il est légal de passer un argument de type char * à strcpy_s. Toutefois, l’inverse n’est pas vrai ; aucune conversion implicite n’existe pour supprimer l’attribut const d’un objet ou d’un pointeur.

Un const pointeur d’un type donné peut être affecté à un pointeur du même type. Toutefois, un pointeur qui ne peut pas const être affecté à un const pointeur. L'exemple de code suivant montre des assignations correctes et incorrectes :

// const_pointer.cpp
int *const cpObject = 0;
int *pObject;

int main() {
pObject = cpObject;
cpObject = pObject;   // C3892
}

L'exemple suivant montre comment déclarer un objet comme const si vous avez un pointeur désignant un pointeur vers un objet.

// const_pointer2.cpp
struct X {
   X(int i) : m_i(i) { }
   int m_i;
};

int main() {
   // correct
   const X cx(10);
   const X * pcx = &cx;
   const X ** ppcx = &pcx;

   // also correct
   X const cx2(20);
   X const * pcx2 = &cx2;
   X const ** ppcx2 = &pcx2;
}

Voir aussi

Pointeurs bruts