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:
Wenn der Eingabestream bis zu einem bestimmten Zeichen in Vorverarbeitungstoken analysiert wurde, ist das nächste Vorverarbeitungstoken die längste Folge von Zeichen, die ein Vorverarbeitungstoken darstellen könnten. [...]
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:
BEISPIEL 2 Das Programmfragment x +++++ y wird als x ++ ++ + y analysiert, was eine Einschränkung für Inkrementoperatoren verletzt, obwohl die Analyse x ++ + ++ y möglicherweise einen korrekten Ausdruck ergibt.
was uns sagt, dass:
a+++++b
wird analysiert als:
a ++ ++ + b
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 ):
Der Operand des Postfix-Inkrement- oder Dekrement-Operators muss einen qualifizierten oder nicht qualifizierten Real- oder Zeigertyp haben und ein modifizierbarer Wert sein.
und
Das Ergebnis des Postfix ++ - Operators ist der Wert des Operanden.
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:
- Behandeln Sie es wie drei Token:
-
, >
und*
- Behandle es als zwei Token:
->
und*
- Behandle es als ein Zeichen:
->*
Die maximale Munch- Regel ermöglicht es, diese Mehrdeutigkeiten zu vermeiden. Der Autor weist darauf hin, dass es ( im C ++ - Kontext ):
löst viel mehr Probleme als es verursacht, aber in zwei häufigen Situationen ist es ein Ärger.
Das erste Beispiel wären Vorlagen, deren Vorlagenargumente auch Vorlagen sind ( die in C ++ 11 gelöst wurden ), zum Beispiel:
list<vector<string>> lovos; // error!
^^
Welche interpretiert die Schließwinkel Klammern als Shift - Operator , und so ein Raum eindeutig zu machen ist erforderlich:
list< vector<string> > lovos;
^
Der zweite Fall betrifft Standardargumente für Zeiger, zum Beispiel:
void process( const char *= 0 ); // error!
^^
würde als *=
Zuweisungsoperator interpretiert werden, besteht die Lösung in diesem Fall darin, die Parameter in der Deklaration zu benennen.