web-dev-qa-db-fra.com

Différence entre C ++ 14 et C ++ 17 en utilisant: `* p ++ = * p`

Lors de l'écriture de code, je suis tombé sur un problème où les valeurs que je définissais étaient incorrectes. J'ai finalement trouvé la ligne coupable et pendant les tests, j'ai constaté qu'elle se comportait différemment sur C++ 14 et C++ 17. Le code est comme suit:

#include <stdio.h>
#include <cstdint>
#include <cstring>

int main()
{
    uint8_t *p = new uint8_t[3];
    memset(p, 0x00, 1);
    p++;
    memset(p, 0xF0, 1);
    p++;
    memset(p, 0xFF, 1);
    p--;
    p--;

    // This line in particular
    *p++ = *p;

    *p++ = 0x0F;

    p--;
    p--;

    printf("Position 0 has value %u\n", *p);
    p++;
    printf("Position 1 has value %u\n", *p);
    p++;
    printf("Position 2 has value %u\n", *p);

    return 0;
}

Sur C++ 14, il imprime:

Position 0 has value 240
Position 1 has value 15
Position 2 has value 255

Et sur C++ 17, il imprime:

Position 0 has value 0
Position 1 has value 15
Position 2 has value 255

Je suis curieux de savoir pourquoi il agit différemment sur différentes versions de C++. Il semble que sur C++ 14 le *p le côté droit de l'affectation est évalué après le ++. Cela a-t-il changé? Et si le ++ a la priorité, pourquoi cela ne se produit-il pas avant la déréférence sur le côté gauche de l'opérateur d'affectation?

36
ApplePearPerson

La lecture et l'écriture de la variable (via le post-incrément) avaient un comportement non défini, car le = n'a pas introduit de point de séquence. Vous pourriez avoir reçu un comportement (ou aucun, ou des explosions) en C++ 14.

Maintenant, un ordre de séquencement est défini pour ce cas et vos résultats C++ 17 sont fiables.

Bien qu'il soit encore mauvais, un code peu clair ne devrait pas être écrit!

57