L’initialisation entre les types “const int ** const” et “int **” n’est pas autorisée, pourquoi?

Avec le compilateur V1.8 z / OS XL C, avec des avertissements augmentés avec INFO (ALL), l’avertissement suivant s’affiche à la ligne 4 du code ci-dessous:

WARNING CCN3196 Initialization between types "const int** const" and "int**" is not allowed. 1 int foo = 0; 2 int *ptr = &foo; 3 const int * const fixed_readonly_ptr = ptr; 4 const int ** const fixed_ptr_to_readonly_ptr = &ptr; 

Je ne peux pas comprendre pourquoi je reçois cet avertissement. Si je peux assigner un pointeur int à un pointeur const à const int (ligne 3), pourquoi ne puis-je pas atsortingbuer l’adresse d’un pointeur int à un pointeur const à pointeur à const int? Qu’est-ce que je rate?

Notez que le code ci-dessus est un exemple réduit illustrant simplement le problème que je rencontre dans une petite quantité de code. Le contexte réel est que j’ai un pointeur const à pointeur à struct (struct s ** const) et que je le passe en tant qu’argument à une fonction dont le paramètre est défini en tant que pointeur const à pointeur à const struct (const struct s ** const). En effet, la fonction ne modifiera pas les données de la structure (d’où le premier const) et ne modifiera pas le paramètre de pointeur qui contient toujours l’adresse transmise (d’où le deuxième const). La valeur du pointeur pointé sur peut être changée par la voie (c’est pourquoi il n’y a PAS de troisième const entre **).

Selon la règle C, vous pouvez convertir un pointeur en un élément, mais un élément du même type, y compris les qualifications const et volatile, plus loin dans la chaîne.

La raison de cette règle est que si la deuxième de ces deux lignes était autorisée:

 int *ptr; const int ** const fixed_ptr_to_readonly_ptr = &ptr; 

alors cela peut être utilisé pour casser la sécurité de type sans casting.

 const int i = 4; // OK, both sides have type const int * *fixed_ptr_to_readonly_ptr = &i; // the value of fixed_ptr_to_readonly_ptr is still &ptr // the value of ptr is now &i; *ptr = 5; // oops, attempt to change the value of i which is const 

C’est une violation de sécurité de type. Considérez ce code (j’ai mélangé const un peu pour préciser s’il s’applique au pointeur ou à la pointe, mais cela signifie sémantiquement la même chose):

 int* p = 0; int const** pp = &p; // presumably ok int const c = 123; *pp = &c; // okay, &c is int const*, and *p is int const* lvalue *p = 666; // okay, *p is int lvalue // wait, so we just changed the value of (const) c above, with no const_cast! 

Ceci est une violation de la sécurité de type. Vous voudrez probablement utiliser un const int * const * à la place. Voir http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17