Différence entre C et en C ++ en ce qui concerne l’opérateur “^ =”

Je veux échanger les valeurs désignées par int *x et par int *y utilisant l’expression

 *x ^= *y ^= *x ^= *y; 

(Eh bien, je sais que cette expression est maladroite, et je veux juste connaître la différence, aucune infraction.) Cela fonctionnait en C ++, mais échouait en C. Cependant, si je la divise en trois parties, comme ci-dessous

 *x ^= *y; *y ^= *x; *x ^= *y; 

Cela fonctionne bien pour les deux langues.

Alors, quelle est la différence de l’opérateur ^= en C et C ++?

La différence ne réside pas dans les pointeurs que vous avez initialement soupçonnés, mais dans l’ordre différent des règles d’évaluation. Dans les “nouvelles” règles C ++ 11 “Séquence avant” , nous avons:

L’effet secondaire (modification de l’argument de gauche) de l’opérateur d’affectation intégré et de tous les opérateurs d’assignation composés intégrés est séquencé après le calcul de la valeur (mais pas les effets secondaires) des arguments gauche et droit, et est séquencé avant. le calcul de la valeur de l’expression d’affectation (c’est-à-dire avant de renvoyer la référence à l’object modifié)

(A partir de cppr .) Cette règle garantit l’évaluation souhaitée de droite à gauche de votre expression.

Contrairement à cela, C et C ++ 98 utilisent des “points de séquence” . Comme il n’y a pas de points de séquence dans la déclaration longue, vous avez plusieurs modifications non séquencées des valeurs pointées par les pointeurs et appelez donc le comportement non défini.

Pour C, gcc prévient à ce propos (en direct) . Apparemment, pour C ++ 98, il utilise déjà les nouvelles règles, ce qui est correct car le comportement indéfini est indéfini.

Le fractionnement de l’instruction résout ce problème, bien sûr, car la fin de l’instruction introduit explicitement les points de séquence où vous en avez besoin. Il est également supérieur parce qu’il est plus lisible et qu’il n’est pas nécessaire de connaître les règles de séquençage pour déterminer si le code est correct ou non.


Pour référence: une excellente explication des règles de séquençage en C ++ peut être trouvée ici .

C’est un comportement indéfini de modifier plusieurs fois la même variable dans une seule instruction. Le compilateur est donc autorisé à faire quoi que ce soit lorsque vous faites *x ^= *y ^= *x ^= *y . C’est la même raison pour laquelle ++i + i++ ou similaire est toujours faux.

Pour répondre à la question posée, il n’y a pas de différence pour les pointeurs bruts entre C et C ++.

Mais je pense que votre vraie question est autre chose …