8

Je crois comprendre que quelque chose comme ceci est correct:Est-ce correct pour int ** et const int ** pour alias?

const int ci = 42; 
const int *cip = &ci; 
int *ip = (int *)cip; 
int j = *ip; 

Qu'en est-ce?

const int ci = 42; 
const int *cip = &ci; 
const int **cipp = &cip; 
int **ipp = (int **)cipp; 
int j = **ipp; 
+0

'int * ip = (int *) cip;' n'est pas OK. Votre compilateur devrait se plaindre de perdre le 'const'. Sinon, utilisez des niveaux d'avertissement plus élevés. Ou quel genre de "OK" pensez-vous? "fonctionne", "fonctionne de manière fiable", "fonctionne de manière portable", "est un bon code", ... – Yunnosch

+7

@Yunnosch: Non. C'est parfaitement correct. La distribution explicite est en fait la façon dont vous * dites * au compilateur que vous * voulez vraiment * supprimer le 'const'. C'est comme ça que vous dites au compilateur de ne pas émettre d'avertissement.Le premier extrait de code est parfaitement légal. – AnT

+0

@AnT Pour le code affiché, l'effacement du const n'est pas nécessaire. Pour d'autres codes, un const qui a un but n'est pas une bonne idée. J'avoue cependant que j'ai confondu les avertissements du compilateur avec le type d'avertissement nitpicky généré par des analyseurs de code statique explicitement super-stricts; que je dois utiliser pour le code dans le travail. Ils ont besoin de plus d'un casting pour arrêter de harceler. C'est un peu brûlé dans ma façon de penser. – Yunnosch

Répondre

5

L'expression *ipp est une lvalue de type int *, mais il est utilisé pour accéder à un objet de type const int * efficace. (A savoir, cip).

Selon la lettre de la norme, il s'agit d'une violation stricte d'alias: la liste des types autorisés à l'alias n'inclut pas l'aliasing T * comme const T * ou vice versa.

Le plus proche exception est celle-ci: (extrait C11 6,5/6)

  • une version qualifié d'un type compatible avec le type effective de l'objet

« qualifié la version "est clairement définie par C11 6.2.5/26:

Chaque type non qualifié a plusieurs versions qualifiées de son type, correspondant aux combinaisons d'un, deux, ou tous les trois des qualificateurs const, volatile et restrict. Les versions qualifiées ou non qualifiées d'un type sont des types distincts appartenant à la même catégorie et ayant les mêmes exigences de représentation et d'alignement. Un type dérivé n'est pas qualifié par les qualificateurs (le cas échéant) du type dont il est dérivé.

Ainsi, l'exception est que T peut être Lissé comme const T et vice versa, mais il ne fait pas exception similaire pour les pointeurs vers des types aliasable. const T * n'est pas une version qualifiée de T *.


Cependant, il est bien sûr la note:

Le but de cette liste est de préciser les circonstances dans lesquelles un objet peut ou non être Aliased

Je ne pourrais pas » Indiquez si l'intention de la règle est const T * et T * d'être aliasable ou non. Il ne me semble pas clair quel est le but de spécifier que T * et const T * ont "les mêmes exigences de représentation et d'alignement" (6.2.5/28) seraient si ce n'est pas aliasable.

+1

Le fait qu'une garantie ne soit utile que si elle a été traitée comme une exception aux règles d'alias n'implique plus que les rédacteurs du compilateur l'interprètent comme une seule. Les garanties de la séquence initiale commune sont fondamentalement inutiles sous gcc et clang sauf dans le mode "no strict aliasing". Ceci étant dit, ni l'un ni l'autre des compilateurs * encore * ne supposent qu'un 'int * p' ne sera pas accédé en utilisant un' int const ** p', et vice versa; Je ne sais pas si cela restera vrai. – supercat