int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
Dieser Code gibt den folgenden Fehler aus:
Fehler: lWert als Inkrementoperand erforderlich
Aber wenn ich setzen Räume in ganz a++ +
und ++b
dann funktioniert es gut.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
Was bedeutet der Fehler im ersten Beispiel?
x+++++y
wird analysiert alsx ++ ++ + y
, was eine Einschränkung für Inkrementoperatoren verletzt, obwohl die Analysex ++ + ++ y
möglicherweise einen korrekten Ausdruck ergibt."Antworten:
printf("%d",a+++++b);
wird(a++)++ + b
gemäß der Maximal Munch Rule interpretiert ! .++
(postfix) wird nicht als a ausgewertet,lvalue
erfordert jedoch, dass sein Operand ein istlvalue
.! 6.4 / 4 besagt, dass das nächste Vorverarbeitungstoken die längste Folge von Zeichen ist, die ein Vorverarbeitungstoken darstellen könnte. "
quelle
Compiler werden schrittweise geschrieben. Die erste Stufe heißt Lexer und verwandelt Zeichen in eine symbolische Struktur. So wird "++" so etwas wie ein
enum SYMBOL_PLUSPLUS
. Später verwandelt die Parser-Stufe dies in einen abstrakten Syntaxbaum, kann jedoch die Symbole nicht ändern. Sie können den Lexer beeinflussen, indem Sie Leerzeichen einfügen (die Endsymbole, sofern sie nicht in Anführungszeichen stehen).Normale Lexer sind gierig (mit einigen Ausnahmen), daher wird Ihr Code als interpretiert
Die Eingabe in den Parser ist ein Strom von Symbolen, daher würde Ihr Code ungefähr so aussehen:
Was der Parser für syntaktisch falsch hält. (BEARBEITEN basierend auf Kommentaren: Semantisch falsch, da Sie ++ nicht auf einen r-Wert anwenden können, was zu einem ++ führt.)
ist
Welches ist in Ordnung. So sind Ihre anderen Beispiele.
quelle
a++
).a++
ergibt einen rwert.x = 10&987&&654&&321
ist illegal, aber seltsamerweisex = 10&987&&654&&&321
ist es legal.Der Lexer verwendet einen sogenannten "Maximum Munch" -Algorithmus, um Token zu erstellen. Das bedeutet, dass beim Einlesen von Zeichen so lange Zeichen gelesen werden, bis auf etwas gestoßen wird, das nicht Teil des gleichen Tokens sein kann wie das, was es bereits hat (z. B. wenn es Ziffern gelesen hat, also eine Zahl, wenn es auf etwas trifft ein
A
, weiß er , dass kein Teil der Zahl sein kann. so stoppt und Blätter dieA
im Eingangspuffer , um die Verwendung als Anfang des nächsten Token). Dieses Token wird dann an den Parser zurückgegeben.In diesem Fall bedeutet dies, dass
+++++
lexed wird alsa ++ ++ + b
. Da das erste Nachinkrement einen r-Wert ergibt, kann das zweite nicht darauf angewendet werden, und der Compiler gibt einen Fehler aus.Nur FWIW, in C ++ können Sie überladen
operator++
, um einen l-Wert zu erhalten, der dies ermöglicht. Beispielsweise:Das kompiliert und läuft (obwohl es nichts tut) mit den C ++ - Compilern, die ich zur Hand habe (VC ++, g ++, Comeau).
quelle
16FA
ist ein völlig in Ordnung hexadezimale Zahl , die ein A enthält0x
am Anfang wird das immer noch wie16
folgt behandeltFA
, keine einzige Hexadezimalzahl.0x
es nicht Teil der Nummer ist.x
Ziffer in Betracht ziehen , schien es ziemlich unnötig.Dieses genaue Beispiel wird im Entwurf der C99-Norm ( gleiche Details in C11 ) in Abschnitt 6.4, Abschnitt 4 der lexikalischen Elemente , behandelt, in dem es heißt:
Dies wird auch als maximale Munch-Regel bezeichnet, die in der lexikalischen Analyse verwendet wird, um Mehrdeutigkeiten zu vermeiden. Dabei werden so viele Elemente wie möglich verwendet, um ein gültiges Token zu bilden.
Der Absatz enthält auch zwei Beispiele. Das zweite entspricht genau Ihrer Frage und lautet wie folgt:
was uns sagt, dass:
wird analysiert als:
Dies verstößt gegen die Einschränkungen für das Nachinkrement, da das Ergebnis des ersten Nachinkrements ein r-Wert ist und das Nachinkrement einen l-Wert erfordert. Dies wird im Abschnitt
6.5.2.4
Postfix-Inkrementierungs- und -Dekrementierungsoperatoren behandelt, der besagt ( Hervorhebung von mir ):und
Das Buch C ++ Gotchas behandelt diesen Fall auch in
Gotcha #17
Maximal Munch Problems. Es ist das gleiche Problem auch in C ++ und enthält auch einige Beispiele. Es erklärt, dass beim Umgang mit den folgenden Zeichensätzen:Der lexikalische Analysator kann eines von drei Dingen ausführen:
-
,>
und*
->
und*
->*
Die maximale Munch- Regel ermöglicht es, diese Mehrdeutigkeiten zu vermeiden. Der Autor weist darauf hin, dass es ( im C ++ - Kontext ):
Das erste Beispiel wären Vorlagen, deren Vorlagenargumente auch Vorlagen sind ( die in C ++ 11 gelöst wurden ), zum Beispiel:
Welche interpretiert die Schließwinkel Klammern als Shift - Operator , und so ein Raum eindeutig zu machen ist erforderlich:
Der zweite Fall betrifft Standardargumente für Zeiger, zum Beispiel:
würde als
*=
Zuweisungsoperator interpretiert werden, besteht die Lösung in diesem Fall darin, die Parameter in der Deklaration zu benennen.quelle
>>
Regel wird gefragt unter: stackoverflow.com/questions/15785496/…Ihr Compiler versucht verzweifelt zu analysieren
a+++++b
und interpretiert es als(a++)++ +b
. Das Ergebnis von post-increment (a++
) ist kein l-Wert , dh es kann nicht erneut nachinkrementiert werden.Bitte schreiben Sie niemals solchen Code in Produktionsqualitätsprogramme. Denken Sie an den armen Kerl, der nach Ihnen kommt und Ihren Code interpretieren muss.
quelle
a ++ gibt den vorherigen Wert zurück, einen r-Wert. Sie können dies nicht erhöhen.
quelle
Weil es undefiniertes Verhalten verursacht.Welches ist es?
Ja, weder Sie noch der Compiler wissen es.BEARBEITEN:
Der wahre Grund ist der, wie von den anderen gesagt:
Es wird interpretiert als
(a++)++ + b
.Nach dem Inkrementieren ist jedoch ein l-Wert erforderlich (eine Variable mit einem Namen). (a ++) gibt jedoch einen r-Wert zurück, der nicht inkrementiert werden kann, was zu der Fehlermeldung führt, die Sie erhalten.
Vielen Dank an die anderen, um darauf hinzuweisen.
quelle
a+++b
a++ + b
a++ ++ +b
das nicht analysiert werden kann.a+++++b
nicht zu bewerten(a++)++)+b
. Wenn Sie diese Klammern einfügen und neu erstellen, ändert sich bei GCC die Fehlermeldung nicht.Ich denke, der Compiler sieht es als
c = ((a ++) ++) + b
++
muss als Operanden einen Wert haben, der geändert werden kann. a ist ein Wert, der geändert werden kann.a++
ist jedoch ein 'rvalue', kann nicht geändert werden.Übrigens ist der Fehler, den ich auf GCC C sehe, der gleiche, aber anders formuliert :
lvalue required as increment operand
.quelle
Befolgen Sie diese Reihenfolge
1. ++ (Pre-Inkrement)
2. + - (Addition oder Subtraktion)
3. "x" + "y" addieren beide Sequenzen
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
quelle