Java-Präfix und unäre Operatoren zusammen

8

Ich habe an Java-Präfix-Operatoren gearbeitet und bin auf dieses Verhalten gestoßen

%Vor%

Warum passiert das?

    
Kiran 11.02.2016, 17:50
quelle

3 Antworten

6

Da sowohl + als auch +++ (oder - und -- ) linksassoziativ sind, wird +++j als ++(+j) ausgewertet. Da ++ nur auf einen l-Wert (d. H. Eine Variable) angewendet werden kann und +j kein l-Wert (Variable) ist, erhalten Sie einen Kompilierungsfehler.

Sie könnten jedoch Klammern verwenden, um dies zu beheben: i = +(++j); .

    
Mureinik 11.02.2016 17:54
quelle
2

Der Compiler verwendet eine gierige Auswahl von Token von links nach rechts. Wenn also +--j angezeigt wird, ist die längste Sequenz, die ein gültiges Token ist, + , da +- kein gültiges Token ist. Daher wird + als erstes Token benötigt. Dann schaut es sich die nächstgrößere Sache an, die als Token identifiziert werden kann, nämlich --j .  Das Ergebnis ist + --j

Für ---j sieht es -- als längstes gültiges Token, dann -j als nächstes gültiges Token und versucht, diese als -- -j zusammenzufassen, was, wie @Mureinik sagte, nicht gültig ist.

    
FredK 11.02.2016 18:29
quelle
1

Bevor der Compiler überhaupt an den Punkt kommt, an dem er weiß, welche Operatoren vorhanden sind, muss er sie analysieren. Ich kann 3 mögliche Parsings für ---j sehen:

  • - - -j // 3 unary - operators
  • -- -j // predecrement -- followed by unary -
  • - --j // unary - followed by predecrement --

Der Fall mit +++j ist äquivalent, wobei preincrement ++ und unary + ersetzt sind.

Warum interpretiert Java es als -- , gefolgt von - , dem zweiten Fall, der der einzige ist, der nicht syntaktisch gültig ist? Der Compiler ist im Allgemeinen gierig . Abschnitt 3.2 der JLS lautet:

  

Ein roher Unicode-Zeichenstrom wird in eine Folge von Token übersetzt, wobei die folgenden drei lexikalischen Übersetzungsschritte verwendet werden, die nacheinander angewendet werden:

...

  

In jedem Schritt wird die längste mögliche Übersetzung verwendet, auch wenn das Ergebnis letztendlich kein korrektes Programm ergibt, während eine andere lexikalische Übersetzung wäre. Es gibt eine Ausnahme: Wenn eine lexikalische Übersetzung in einem Typkontext (§4.11) auftritt und der Eingabestream zwei oder mehr aufeinanderfolgende & gt; Zeichen, denen ein nicht & gt; Charakter, dann jeder & gt; Das Zeichen muss in das Token für den numerischen Vergleichsoperator & gt; übersetzt werden.

(Hervorhebung meiner)

Der Compiler sieht gierig zwei - -Zeichen und deklariert sofort das -- -Token, ohne das dritte - als nächstes zu betrachten.

Das hat nichts mit Assoziativität des Operators oder sogar Vorrang für den Operator und alles was mit dem Syntax-Parsing zu tun hat.

Wie schon von @Mureinik erwähnt, wird das korrekte Platzieren von klärenden Klammern den Compiler zwingen, es richtig zu parsen. Dies wird jedoch erreicht, indem die Zeichen in verschiedene Token aufgespalten werden, nicht indem die Priorität der Operationen geändert wird.

Der Ausdruck -++j ist von der Gierigkeit des Compilers nicht betroffen; -+ ist kein gültiges Token, daher wird es korrekt als Token - gefolgt vom Token ++ und ähnlich für den Ausdruck +--j analysiert.

    
rgettman 11.02.2016 18:29
quelle