int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
Ce code donne l'erreur suivante:
erreur: lvalue requise comme opérande d'incrément
Mais si je mets des espaces partout a++ +
et ++b
, alors cela fonctionne bien.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
Que signifie l'erreur dans le premier exemple?
x+++++y
est analysé commex ++ ++ + y
, ce qui viole une contrainte sur les opérateurs d'incrémentation, même si l'analysex ++ + ++ y
peut produire une expression correcte."Réponses:
printf("%d",a+++++b);
est interprété comme(a++)++ + b
selon la règle Maximal Munch ! .++
(postfix) n'évalue pas à unlvalue
mais il nécessite que son opérande soit unlvalue
.! 6.4 / 4 indique que le prochain jeton de prétraitement est la plus longue séquence de caractères qui pourrait constituer un jeton de prétraitement "
la source
Les compilateurs sont écrits par étapes. La première étape s'appelle le lexer et transforme les caractères en une structure symbolique. Donc "++" devient quelque chose comme un
enum SYMBOL_PLUSPLUS
. Plus tard, l'étape de l'analyseur transforme cela en un arbre de syntaxe abstrait, mais il ne peut pas changer les symboles. Vous pouvez affecter le lexer en insérant des espaces (qui terminent les symboles sauf s'ils sont entre guillemets).Les lexers normaux sont gourmands (à quelques exceptions près), donc votre code est interprété comme
L'entrée de l'analyseur est un flux de symboles, donc votre code serait quelque chose comme:
Ce que l'analyseur pense est syntaxiquement incorrect. (EDIT basé sur les commentaires: sémantiquement incorrect car vous ne pouvez pas appliquer ++ à une valeur r, ce qui entraîne un ++)
est
Ce qui est ok. Vos autres exemples aussi.
la source
a++
).a++
donne une rvalue.x = 10&987&&654&&321
est illégal, mais curieusementx = 10&987&&654&&&321
c'est légal.Le lexer utilise ce que l'on appelle généralement un algorithme "maximum munch" pour créer des jetons. Cela signifie que lorsqu'il lit des caractères, il continue à lire des caractères jusqu'à ce qu'il rencontre quelque chose qui ne peut pas faire partie du même jeton que ce qu'il a déjà (par exemple, s'il a lu des chiffres, alors ce qu'il a est un nombre, s'il rencontre an
A
, il sait que cela ne peut pas faire partie du nombre. Il s'arrête donc et laisse leA
dans le tampon d'entrée pour l'utiliser comme début du jeton suivant). Il renvoie ensuite ce jeton à l'analyseur.Dans ce cas, cela signifie qu'il
+++++
est défini commea ++ ++ + b
. Puisque le premier post-incrémentation produit une rvalue, la seconde ne peut pas lui être appliquée et le compilateur donne une erreur.Juste FWIW, en C ++, vous pouvez surcharger
operator++
pour générer une lvalue, ce qui permet à cela de fonctionner. Par exemple:Le compile et s'exécute (bien qu'il ne fasse rien) avec les compilateurs C ++ que j'ai sous la main (VC ++, g ++, Comeau).
la source
16FA
est un nombre hexadécimal parfaitement fin qui contient un A.0x
au début, il traitera toujours cela comme16
suivi parFA
, pas un seul nombre hexadécimal.0x
ne faisait pas partie du nombre.x
un chiffre, cela semblait tout à fait inutile.Cet exemple exact est couvert dans le projet de norme C99 ( mêmes détails dans C11 ) section 6.4 Éléments lexicaux paragraphe 4 qui dit:
qui est également connue sous le nom de règle de munch maximal qui est utilisée dans l'analyse lexicale pour éviter les ambiguïtés et fonctionne en prenant autant d'éléments que possible pour former un jeton valide.
le paragraphe contient également deux exemples, le second correspond exactement à votre question et se présente comme suit:
ce qui nous dit que:
sera analysé comme suit:
ce qui viole les contraintes de post-incrémentation puisque le résultat du premier post-incrément est une rvalue et que post-increment nécessite une lvalue. Ceci est couvert dans la section
6.5.2.4
Opérateurs d'incrémentation et de décrémentation de Postfix qui dit (c'est moi qui souligne ):et
Le livre C ++ Gotchas couvre également ce cas dans
Gotcha #17
Maximal Munch Problems c'est le même problème dans C ++ et il donne également quelques exemples. Il explique que lorsqu'il s'agit de l'ensemble de caractères suivant:l'analyseur lexical peut faire l'une des trois choses suivantes:
-
,>
et*
->
et*
->*
Le munch maximal règle de permet d'éviter ces ambiguïtés. L'auteur précise qu'il ( dans le contexte C ++ ):
Le premier exemple serait des modèles dont les arguments de modèle sont également des modèles ( ce qui a été résolu en C ++ 11 ), par exemple:
Ce qui interprète les crochets angulaires de fermeture comme l' opérateur de décalage , et donc un espace est nécessaire pour lever l'ambiguïté:
Le deuxième cas concerne les arguments par défaut pour les pointeurs, par exemple:
serait interprété comme un
*=
opérateur d'affectation, la solution dans ce cas est de nommer les paramètres dans la déclaration.la source
>>
règle est posée sur: stackoverflow.com/questions/15785496/…Votre compilateur essaie désespérément d'analyser
a+++++b
et l'interprète comme(a++)++ +b
. Maintenant, le résultat du post-incrément (a++
) n'est pas une lvalue , c'est-à-dire qu'il ne peut pas être post-incrémenté à nouveau.Veuillez ne jamais écrire un tel code dans des programmes de qualité de production. Pensez au pauvre type qui vient après vous qui a besoin d'interpréter votre code.
la source
a ++ renvoie la valeur précédente, une rvalue. Vous ne pouvez pas augmenter cela.
la source
Parce que cela provoque un comportement indéfini.Laquelle est-ce?
Ouais, ni vous ni le compilateur ne le savez.ÉDITER:
La vraie raison est celle que disent les autres:
Il est interprété comme
(a++)++ + b
.mais post-incrémentation nécessite une lvalue (qui est une variable avec un nom) mais (a ++) renvoie une rvalue qui ne peut pas être incrémentée conduisant ainsi au message d'erreur que vous obtenez.
Merci aux autres de le signaler.
la source
a+++b
est toujours de mêmea++ + b
a++ ++ +b
qui ne peut pas être analysé.a+++++b
(a++)++)+b
Je pense que le compilateur le voit comme
c = ((a ++) ++) + b
++
doit avoir comme opérande une valeur modifiable. a est une valeur qui peut être modifiée.a++
cependant est une 'rvalue', elle ne peut pas être modifiée.Soit dit en passant l'erreur que je vois sur GCC C est le même, mais différemment rédigé:
lvalue required as increment operand
.la source
Suivez cet ordre préalable
1. ++ (pré-incrément)
2. + - (addition ou soustraction)
3. "x" + "y" ajouter à la fois la séquence
int a = 5,b = 2; printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment return 0; //it is 5+3=8
la source