web-dev-qa-db-fra.com

Pourquoi "++ i ++" n'est-il pas valide alors que (++ i) ++ est valide?

Prenons le code suivant:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

Il se compile avec les éléments suivants avec une erreur:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

Cela me semble juste. L'incrément de suffixe a une priorité plus élevée que l'incrément de préfixe, donc le code est analysé comme int b = ++(i++); et i est une valeur r. D'où l'erreur.

Considérons maintenant cette variante avec des parenthèses pour remplacer les priorités par défaut:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

Ce code compile et renvoie 3. À lui seul, cela me semble juste, mais il semble en contradiction avec le premier code.

La question: pourquoi (++i) Est un lvalue alors que i ne l'est pas?

Merci!

MISE À JOUR: le message d'erreur ci-dessus provenait de gcc (x86-64 9.2). Voici le rendu exact: erreur avec gcc

Clang x86-64 9.0.0 a un message assez différent: erreur avec clang

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

Avec GCC, vous avez l'impression que le problème vient de l'opérateur postfix et vous pouvez alors vous demander pourquoi ++i Est OK alors que i ne l'est pas, d'où ma question. Avec Clang, il est plus clair que le problème vient de l'opérateur de préfixe.

14
Bktero

i et ++i sont tous deux des valeurs l, mais i++ est une valeur r.

++(i++) ne peut pas être valide, car le préfixe ++ est appliqué à i++, qui est une valeur r. Mais (++i)++ Est très bien car ++i Est une valeur l.

Notez qu'en C, la situation est différente; i++ Et ++i Sont tous deux des valeurs r. (C'est un exemple de la raison pour laquelle les gens devraient cesser de supposer que C et C++ ont les mêmes règles. Les gens insèrent ces hypothèses dans leurs questions, qui doivent ensuite être réfutées.)

23
Brian

Cette déclaration

int b = ++i++;

est équivalent à

int b = ++( i++ );

L'opérateur d'incrémentation postfixe renvoie la valeur de l'opérande avant l'incrémentation.

De la norme C++ 17 (8.2.6 Incrémentation et décrémentation)

1 La valeur d'une expression postfix ++ est la valeur de son opérande ...Le résultat est une valeur.

Alors que l'opérateur d'incrément unaire renvoie lvalue après son incrément. Donc, cette déclaration

int b = (++i)++;

est valable. Vous pourriez par exemple écrire

int b = (++++++++i)++;

De la norme C++ 17 (8.3.2 Incrémentation et décrémentation)

1 L'opérande de préfixe ++ est modifié en ajoutant 1. L'opérande doit être une valeur l modifiable. Le type de l'opérande doit être un type arithmétique autre que cv bool, ou un pointeur vers un type d'objet complètement défini. Le résultat est l'opérande mis à jour; c'est une lvalue, et c'est un champ de bits si l'opérande est un champ de bits ....

Faites attention qu'en C, les deux opérateurs retournent une valeur au lieu de lvalue. Donc en C cette déclaration

int b = (++i)++;

est invalide.

4
Vlad from Moscow

donc le code est analysé comme int b = ++ (i ++); et i est une valeur r.

Non. i n'est pas une valeur r. i est une valeur l. i++ est une rvalue (prvalue pour être spécifique).

3
eerorika