Après des recherches, j'ai lu que l'opérateur d'incrémentation nécessite que l'opérande ait un objet de données modifiable: https://en.wikipedia.org/wiki/Increment_and_decrement_operators .
À partir de là, je suppose que cela donne une erreur de compilation car il (a+b)
s'agit d'un entier temporaire et n'est donc pas modifiable.
Cette compréhension est-elle correcte? C'était la première fois que j'essayais de rechercher un problème, donc s'il y avait quelque chose que j'aurais dû chercher, veuillez le conseiller.
c = a + b + 1
votre intention est plus claire et plus courte à taper. Les opérateurs d'incrémentation / décrémentation font deux choses: 1. eux et leur argument forment une expression (qui peut être utilisée, par exemple dans une boucle for), 2. ils modifient l'argument. Dans votre exemple, vous utilisez la propriété 1. mais pas la propriété 2., puisque vous rejetez l'argument modifié. Si vous n'avez pas besoin de la propriété 2. et que vous voulez simplement l'expression, vous pouvez simplement écrire une expression, par exemple x + 1 au lieu de x ++.Réponses:
C'est juste une règle, c'est tout, et est peut-être là pour (1) faciliter l'écriture des compilateurs C et (2) personne n'a convaincu le comité de normalisation C de l'assouplir.
De manière informelle, vous ne pouvez écrire que
++foo
sifoo
peut apparaître sur le côté gauche d'une expression d'affectation commefoo = bar
. Puisque vous ne pouvez pas écrirea + b = bar
, vous ne pouvez pas écrire non++(a + b)
plus.Il n'y a pas de vraie raison pour laquelle
a + b
ne pourrait pas produire un temporaire sur lequel++
peut fonctionner, et le résultat de cela est la valeur de l'expression++(a + b)
.la source
++
parfois avait un effet secondaire de modifier quelque chose et parfois tout simplement pas.La norme C11 indique dans la section 6.5.3.1
Et "lvalue modifiable" est décrite dans la section 6.3.2.1 sous-section 1
Donc
(a+b)
n'est pas une lvalue modifiable et n'est donc pas éligible pour l'opérateur d'incrémentation de préfixe.la source
Vous avez raison. la
++
tente d'attribuer la nouvelle valeur à la variable d' origine. Donc++a
, prendra la valeur dea
, y ajoutera1
, puis l'attribuera à nouveaua
. Puisque, comme vous l'avez dit, (a + b) est une valeur temporaire et non une variable avec une adresse mémoire attribuée, l'affectation ne peut pas être effectuée.la source
Je pense que vous avez principalement répondu à votre propre question. Je pourrais faire un petit changement dans votre formulation et remplacer "variable temporaire" par "rvalue" comme mentionné par C.Gibbons.
Les termes variable, argument, variable temporaire et ainsi de suite deviendront plus clairs au fur et à mesure que vous en apprendrez sur le modèle de mémoire de C (cela ressemble à un bel aperçu: https://www.geeksforgeeks.org/memory-layout-of-c-program/ ).
Le terme «rvalue» peut sembler opaque lorsque vous débutez, donc j'espère que ce qui suit vous aidera à développer une intuition à ce sujet.
Lvalue / rvalue parlent des différents côtés d'un signe égal (opérateur d'affectation): lvalue = côté gauche (L minuscule, pas un "un") rvalue = côté droit
Apprendre un peu comment C utilise la mémoire (et les registres) sera utile pour voir pourquoi la distinction est importante. Dans de larges coups de pinceau , le compilateur crée une liste d'instructions en langage machine qui calculent le résultat d'une expression (la rvalue), puis place ce résultat quelque part (la lvalue). Imaginez un compilateur traitant le fragment de code suivant:
Dans le pseudocode d'assemblage, cela pourrait ressembler à cet exemple de jouet:
L'opérateur ++ (et son équivalent -) a besoin d'un "quelque part" à modifier, essentiellement tout ce qui peut fonctionner comme une lvalue.
Comprendre le modèle de mémoire C sera utile car vous aurez une meilleure idée de la façon dont les arguments sont passés aux fonctions et (éventuellement) comment travailler avec l'allocation de mémoire dynamique, comme la fonction malloc (). Pour des raisons similaires, vous pouvez étudier une programmation d'assemblage simple à un moment donné pour avoir une meilleure idée de ce que fait le compilateur. De plus, si vous utilisez gcc , l' option -S "Arrêtez après l'étape de compilation proprement dite; ne pas assembler." peut être intéressant (même si je recommanderais de l'essayer sur un petit fragment de code).
En passant: l'instruction ++ existe depuis 1969 (bien qu'elle ait commencé dans le prédécesseur de C, B):
Suite à cette référence wikipedia vous amènera à un article intéressant de Dennis Ritchie (le «R» dans «K&R C») sur l'histoire du langage C, lié ici pour plus de commodité: http://www.bell-labs.com/ usr / dmr / www / chist.html où vous pouvez rechercher "++".
la source
La raison en est que la norme exige que l'opérande soit une valeur l. L'expression
(a+b)
n'est pas une lvalue, donc l'application de l'opérateur d'incrément n'est pas autorisée.Maintenant, on pourrait dire « OK, c'est bien la raison, mais il est en fait pas * raison réelle * autre que » , mais malheureusement le libellé particulier de la façon dont l'opérateur travaille factuellement n'exige que ce soit le cas.
Evidemment, vous ne pouvez pas écrire
E += 1
si ceE
n'est pas une lvalue. Ce qui est dommage car on aurait tout aussi bien pu dire: "incrémente E de un" et c'est fait. Dans ce cas, appliquer l'opérateur sur une valeur non-l serait (en principe) parfaitement possible, au détriment de rendre le compilateur légèrement plus complexe.Maintenant, la définition pourrait être reformulée de manière triviale (je pense que ce n'est même pas à l'origine C mais un héritage de B), mais cela changerait fondamentalement le langage en quelque chose qui n'est plus compatible avec ses anciennes versions. Étant donné que les avantages possibles sont plutôt faibles mais que les implications possibles sont énormes, cela ne s'est jamais produit et ne se produira probablement jamais.
Si vous considérez C ++ en plus de C (la question est étiquetée C, mais il y a eu une discussion sur les surcharges d'opérateurs), l'histoire devient encore plus compliquée. En C, il est difficile d'imaginer que cela puisse être le cas, mais en C ++, le résultat de
(a+b)
pourrait très bien être quelque chose que vous ne pouvez pas incrémenter du tout, ou l'incrémentation pourrait avoir des effets secondaires très considérables (pas seulement l'ajout de 1). Le compilateur doit être capable de faire face à cela et de diagnostiquer les cas problématiques au fur et à mesure qu'ils se produisent. Sur une lvalue, c'est encore un peu trivial à vérifier. Ce n'est pas le cas pour toute sorte d'expression aléatoire à l'intérieur d'une parenthèse que vous lancez sur le pauvre.Ce n'est pas une vraie raison pour laquelle ça ne pourrait pas être fait, mais cela explique certainement pourquoi les gens qui l'ont implémenté ne sont pas précisément ravis d'ajouter une telle fonctionnalité qui promet très peu d'avantages à très peu de gens.
la source
(a + b) donne une valeur r, qui ne peut pas être incrémentée.
la source
++ essaie de donner la valeur à la variable d'origine et puisque (a + b) est une valeur temporaire, il ne peut pas effectuer l'opération. Et ce sont essentiellement des règles des conventions de programmation C pour faciliter la programmation. C'est tout.
la source
Lorsque l'expression ++ (a + b) est exécutée, alors par exemple:
la source