Namespaces
Variants

const type qualifier

From cppreference.net

Chaque type individuel dans le système de types du C possède plusieurs versions qualifiées de ce type, correspondant à un, deux ou l'ensemble des trois qualificateurs const , volatile , et, pour les pointeurs vers des types objet, restrict . Cette page décrit les effets du qualificateur const .

Les objets déclarés avec des types qualifiés const peuvent être placés en mémoire morte par le compilateur, et si l'adresse d'un objet const n'est jamais prise dans un programme, il peut ne pas être stocké du tout.

Toute tentative de modifier un objet dont le type est qualifié const entraîne un comportement indéfini.

const int n = 1; // objet de type qualifié const
int* p = (int*)&n;
*p = 2; // comportement indéfini

const s'applique uniquement aux expressions lvalue ; chaque fois qu'une expression const lvalue est utilisée dans un contexte qui ne nécessite pas de lvalue, son qualificatif const est perdu (notez que le qualificatif volatile, s'il est présent, n'est pas perdu).

Les expressions lvalue qui désignent des objets de type qualifié const et les expressions lvalue qui désignent des objets de type struct ou union avec au moins un membre de type qualifié const (y compris les membres d'agrégats ou d'unions contenus récursivement), ne sont pas des lvalues modifiables . En particulier, elles ne sont pas assignables :

const int n = 1; // objet de type const
n = 2; // erreur : le type de n est qualifié const
int x = 2; // objet de type non qualifié
const int* p = &x;
*p = 3; // erreur : le type de la lvalue *p est qualifié const
struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
s1 = s2; // erreur : le type de s1 est non qualifié, mais il a un membre const

Un membre d'une structure ou d'un type union qualifié const acquiert la qualification du type auquel il appartient (à la fois lorsqu'il est accédé en utilisant l'opérateur . ou l'opérateur -> ).

struct s { int i; const int ci; } s;
// le type de s.i est int, le type de s.ci est const int
const struct s cs;
// les types de cs.i et cs.ci sont tous deux const int

Si un type tableau est déclaré avec le qualificatif de type const (via l'utilisation de typedef ), le type tableau n'est pas qualifié const, mais son type d'élément l'est.

(jusqu'à C23)

Un type tableau et son type d'élément sont toujours considérés comme étant identiquement qualifiés const.

(depuis C23)
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // tableau de tableaux de const int
int* pi = a[0]; // Erreur : a[0] a le type const int*
void *unqual_ptr = a; // OK jusqu'à C23 ; erreur depuis C23
// Notes : clang applique la règle en C++/C23 même dans les modes C89-C17

Si un type de fonction est déclaré avec le qualificatif de type const (via l'utilisation d'un typedef ), le comportement est indéfini.

Dans une déclaration de fonction, le mot-clé const peut apparaître à l'intérieur des crochets utilisés pour déclarer un type de tableau d'un paramètre de fonction. Il qualifie le type de pointeur vers lequel le type de tableau est transformé.

Les deux déclarations suivantes déclarent la même fonction :

void f(double x[const], const double y[const]);
void f(double * const x, const double * const y);
(depuis C99)

Les littéraux composés qualifiés const ne désignent pas nécessairement des objets distincts ; ils peuvent partager le stockage avec d'autres littéraux composés et avec des littéraux de chaîne qui ont une représentation identique ou chevauchante.

const int* p1 = (const int[]){1, 2, 3};
const int* p2 = (const int[]){2, 3, 4}; // la valeur de p2 peut être égale à p1+1
_Bool b = "foobar" + 3 == (const char[]){"bar"}; // la valeur de b peut être 1
(depuis C99)

Un pointeur vers un type non-const peut être implicitement converti en un pointeur vers la version qualifiée const du même type ou d'un type compatible . La conversion inverse nécessite une expression de cast.

int* p = 0;
const int* cp = p; // OK : ajoute des qualificateurs (int vers const int)
p = cp; // Erreur : supprime des qualificateurs (const int vers int)
p = (int*)cp; // OK : cast

Notez qu'un pointeur vers un pointeur vers T n'est pas convertible en pointeur vers un pointeur vers const T ; pour que deux types soient compatibles, leurs qualifications doivent être identiques.

char *p = 0;
const char **cpp = &p; // Erreur : char* et const char* ne sont pas des types compatibles
char * const *pcp = &p; // OK, ajoute des qualificateurs (char* vers char*const)

Table des matières

Mots-clés

const

Notes

C a adopté le qualificateur const de C++, mais contrairement à C++, les expressions de type qualifié const en C ne sont pas des expressions constantes ; elles ne peuvent pas être utilisées comme étiquettes case ou pour initialiser des objets de durée de stockage statique et de durée de stockage thread , énumérateurs , ou tailles de champs de bits . Lorsqu'elles sont utilisées comme tailles de tableaux , les tableaux résultants sont des VLA.

Références

  • Norme C17 (ISO/IEC 9899:2018):
  • 6.7.3 Qualificateurs de type (p: 87-90)
  • Norme C11 (ISO/CEI 9899:2011) :
  • 6.7.3 Qualificateurs de type (p: 121-123)
  • Norme C99 (ISO/CEI 9899:1999) :
  • 6.7.3 Qualificateurs de type (p: 108-110)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 6.5.3 Qualificateurs de type

Voir aussi

Documentation C++ pour les qualificateurs de type cv ( const et volatile )