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


14

Prenons le code suivant:

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

Il se compile avec ce qui suit 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 iest une valeur r. D'où l'erreur.

Considérons maintenant cette variante entre 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)un lvaluequand ine 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 est avec l'opérateur postfix et vous pouvez alors vous demander pourquoi ++iest OK alors que ce in'est pas le cas, d'où ma question. Avec Clang, il est plus clair que le problème vient de l'opérateur de préfixe.


C'était à l'origine tagué avec C, ce n'est certainement pas valide C.
Antti Haapala

En effet désolé! J'ai supposé que le comportement était le même en C ...
Bktero

Réponses:


23

iet ++isont tous les deux lvalues, mais i++est une rvalue.

++(i++)ne peut pas être valide, car le préfixe ++est appliqué à i++, qui est une valeur r. Mais (++i)++c'est bien parce que ++ic'est une valeur.

Notez qu'en C, la situation est différente; i++et ++isont tous les deux des valeurs. (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.)


4

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 .

Tandis 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 valeur l , et c'est un champ binaire si l'opérande est un champ binaire ....

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.


3

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

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.