web-dev-qa-db-fra.com

Le comportement non défini de ++ * ptr ++ est-il en c ++?

On m'a posé la question suivante dans un test (je ne voulais pas l'écrire moi-même. Le test le demandait. Je connais encore son mauvais code) sur l'évaluation de ++ * ptr ++

int Ar[ ] = { 6 , 3 , 8 , 10 , 4 , 6 , 7} ;
int *Ptr = Ar  ;
cout<<++*Ptr++  ;

Cependant, je soupçonne qu’il s’agit d’un comportement indéfini, car il peut s’agir de (++*ptr)++ ou de ++(*ptr++). Est-ce Je ne connais pas très bien la documentation et je n’ai rien trouvé.

56
SHM

Cependant, je soupçonne qu’il s’agit d’un comportement indéfini, car il peut s’agir de _(++*ptr)++_ ou ++(*ptr++). Est ce

Pas vraiment, contrairement au comportement d'exécution, qui laisse une grande marge de manœuvre aux développeurs, en C++, l'analyse elle-même obéit à des règles assez strictes et bien définies.1. En effet, si on regarde règles de priorité , _++*Ptr++_ est en fait analysé comme ++(*(Ptr++)).

Cette question piège fait plutôt allusion au comportement non défini d'expressions telles que i = ++i + ++i , où vous avez une valeur qui apparaît plusieurs fois dans une expression et qui est soumise à une modification par un côté. -effet de l'expression elle-même. De telles expressions sont illégales, car, sauf s’il existe un opérateur qui séquence les effets secondaires2, le moment exact dans lequel elles sont appliquées n’est pas défini, il n’est donc pas défini exactement les valeurs que i prendrait dans les différents points de l’expression.

Néanmoins, il n’ya pas de comportement indéfini ici, car tous les effets secondaires de l’expression agissent sur des valeurs différentes, qui apparaissent une seule fois dans l’expression: le "inner" _++_ affecte Ptr, tandis que l’extérieur affecte le valeur indiquée à l'origine par Ptr, c'est-à-dire _Ar[0]_.

_++(*(Ptr++))
     ^^^^^____increments Ptr, returning its original value
   ^^^^^^^^______dereferences the original Ptr, AKA &Ar[0]
^^^^^^^^^^^^_______ increments Ar[0]
_

Cela étant dit, si je voyais un jour une telle expression dans une base de code, je ferais tout en mon pouvoir pour trouver l'auteur et m'assurer que cela ne se reproduira plus.


  1. Si parfois très bizarre et absurdement coûteux à mettre en œuvre. Néanmoins, il existe des exemples de comportement indéfini dans la norme décrivant certains cas critiques de l'analyse, mais leur ordre de grandeur est moins omniprésent que le comportement indéfini "d'exécution" .
  2. Un résumé pratique de ces règles peut être trouvé ici ; Fait intéressant, des garanties supplémentaires ont été ajoutées dans C++ 17.
76
Matteo Italia

Cette

++*Ptr++;

ne cause pas de U.B et est évalué comme ++(*(Ptr++))

  • ptr++;/* address post incremented i.e doesn't change here itself */
  • *ptr;/* dereference same address i.e value at location where ptr earlier pointed i.e 6 */
  • ++*ptr;/* value changed where ptr pointed i.e Ar[0] becomes 7 */

Notez que post increments Ptr++ évalué comme

  • Ptr;/* Ptr doesn't change here itself in same expression */
  • Ptr = Ptr + 1;/* in next expression, Ptr considers the incremented one */
23
Achal