nxclass
Goto Top

Operator Reihenfolge - zweiter Operand

hallo,
ich habe schon seit geraumer Zeit mit PHP zu tun, aber scheinbar bei simplen Sachen lernt man immer was dazu.

Bitte kann mir jemand die Ergebnisse der folgenden Berechnungen erklären ?
$foo = 5;
echo $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 17  
$foo = 5;
echo $foo + $foo++ ."\n"; # 5+5 (+1)? - Ergebnis: 11  
$foo = 5;
echo $foo + $foo + $foo++ ."\n"; # 5+5+5 (+1)? - Ergebins: 15  
$foo = 5;
echo (int) $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 16  
Kommentar vom Moderator masterG am Mar 28, 2011 um 15:14:18 Uhr
Editierfunktion ist auch nützlich

Content-Key: 162833

Url: https://administrator.de/contentid/162833

Printed on: May 23, 2024 at 19:05 o'clock

Member: EvilMoe
EvilMoe Mar 17, 2011 at 10:45:18 (UTC)
Goto Top
$foo = 5;
echo $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 17
5 + 6 + 6 = 17

$foo hast du ab dem 2. Operator um 1 erhöht und bleibt später natürlich so erhalten.
Besser zu verstehen wäre es vllt. so: $foo = $foo + 1 ; ist das gleiche.


$foo = 5;
echo $foo + $foo++ ."\n"; # 5+5 (+1)? - Ergebnis: 11
5 + 6 = 11
$foo ist ja 5 und erhöhst in beim 2. Operator wiede rum 1.


$foo = 5;
echo $foo + $foo + $foo++ ."\n"; # 5+5+5 (+1)? - Ergebins: 15
Mhh komisch, kann ich mir auch nicht erklären warum da 15 raus kommt und nicht 16.


$foo = 5;
echo (int) $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 16
Passt irgentwie auch nicht in meine Logik, ich hätte auf 5+6+6 getippt.


Ich vermute mal das es ein Problem von den Typen sein kann.
Member: Guenni
Guenni Mar 18, 2011 at 14:59:25 (UTC)
Goto Top
@nxclass,

anscheinend hast du hier einen Fall (oder einen Bug face-smile ) konstruiert, den der Interpreter nicht korrekt verarbeitet, weil du immer

den selben Varablennamen verwendest.

Operatoren geben wie Funktionen ein Ergebnis zurück. Für den zusammengesetzten Operator ++ gibt es zwei Notationen:

Die Präfix-Notation (++$var) und die Postfix-Notation ($var++). Im ersten Fall wird der Variableninhalt um 1 inkrementiert und danach

das Ergebnis zurückgegeben. Im zweiten Fall wird der Variableninhalt zurückgegeben und danach inkrementiert.

<?php
$foo=5;
echo $foo++."<br>"; // Ergebnis: 5, Wert wird "nach" der Ausgabe inkrementiert  
echo ++$foo."<br>"; // Ergebnis: 7, Wert wurde "vor" der Ausgabe nochmal inkrementiert  
?>

Was jetzt bei deinem Beispiel passiert, kann ich auch (noch) nicht nachvollziehen, aber wenn du anstatt einem Variablennamen

versch. Variablennamen verwendest, arbeiten die Operatoren auch korrekt:

<?php
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + $foo2++ + $foo3."<br>"; //Ergebnis: 15, Wert($foo2) wird "nach" der Ausgabe inkrementiert  
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + ++$foo2 + $foo3."<br>"; //Ergebnis: 16, Wert($foo2) wird "vor" der Ausgabe inkrementiert  
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + $foo2 + $foo3++."<br>"; //Ergebnis: 15, Wert($foo3) wird "nach" der Ausgabe inkrementiert  
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + $foo2 + ++$foo3."<br>"; //Ergebnis: 16, Wert($foo3) wird "vor" der Ausgabe inkrementiert  
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + ++$foo2 + ++$foo3."<br>"; //Ergebnis: 17, Werte($foo2,$foo3) werden "vor" der Ausgabe inkrementiert  
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + $foo2++ + $foo3++."<br>"; //Ergebnis: 15, Werte($foo2,$foo3) werden "nach" der Ausgabe inkrementiert  
?>


Gruß
Günni
Member: dog
Solution dog Mar 18, 2011 at 23:30:44 (UTC)
Goto Top
Die Ursache ist hier ganz einfach die Operator-Präzedenz (Das wäre übrigens eine nette Frage für einen Programmiertest face-devilish).
++ ist ein unärer Operator und bindet immer stärker als alle binären Operatoren.

Entsprechend ist die Rechnung:

echo $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 17

= ($foo + $foo++) + $foo
=   2       1        3   #Auswertungsreihenfolge
=   6   +   5     +  6
(Warum ich da jetzt klammern gesetzt habe erkläre ich unten)

echo $foo + $foo++ ."\n"; # 5+5 (+1)? - Ergebnis: 11
= $foo + $foo++
=   2  +   1     #Auswertungsreihenfolge
=   6  +   5

echo $foo + $foo + $foo++ ."\n"; # 5+5+5 (+1)? - Ergebins: 15

Der Grund ist hier, dass + ein Binärer Operator ist.
Er hat nur exakt zwei Seiten (links und rechts), PHP muss also implizit Klammern, und klammern binden immer noch stärker also unäre Operatoren.

Hier steht also:

= ($foo + $foo) + $foo++
=   1       2        3   #Auswertungsreihenfolge
=   5   +   5   +  5

Anders gesagt: Für Programmiersprachen gilt das Assoziativgesetz (Klammervertauschungsgesetz) nicht!

echo (int) $foo + $foo++ + $foo ."\n"; # 5+5+6 - Ergebnis: 16

Das Casten ist ebenfalls ein unärer Operator.
Die unären Operatoren werden wieder von links ausgewertet, weshalb folgendes passiert:

= (int)($foo) + $foo++ + $foo
=       1         2       3      #Auswertungsreihenfolge
=       5     +   5    +  6

Das ist natürlich nicht zu verwechseln mit (int)($foo + $foo++ + $foo)

Frage beantwortet? face-smile

Kleine Überlegung zum Schluss:

0 < 7 < 5

Kommt hier true oder false raus und warum? face-wink
Der Code funktioniert nicht in PHP, aber in C
Member: Guenni
Guenni Mar 19, 2011 at 16:39:59 (UTC)
Goto Top
Frage beantwortet?

Nöö!

<?php
$foo=5;
echo $foo + $foo++ + $foo;
?>

Ergibt 17 face-sad

<?php
$foo1=5;
$foo2=5;
$foo3=5;
echo $foo1 + $foo2++ + $foo3; 
?>

Ergibt 15 face-smile

Auch Klammern bringt nix:

<?php
$foo=5;
echo $foo + $foo++ + $foo;
?>


Ergibt 17


<?php
$foo=5;
echo ($foo + $foo++) + $foo;
?>

Ergibt?? Na . . . , 17

Gruß
Günni
Member: dog
dog Mar 19, 2011 at 16:44:49 (UTC)
Goto Top
Ergibt 17 face-sad

Richtig, wie von mir oben erklärt

Ergibt 15 face-smile

Weil es 3 Variablen sind.
Das Postkrement wird zwar angewendet, aber gleich verworfen im Gegensatz zu oben, wo die variable nach dem Postkrement gleich noch zweimal benutzt wird!

Ergibt 17

Kein Unterschied zum ersten Beispiel?

Ergibt?? Na . . . , 17

Das ist genau das erste Beispiel mit der Klammerung, die PHP implizit selber einsetzt.


Nochmal:
  • Ein binärer Operator wie + hat nur genau EINE linke und EINE rechte Seite
  • Ein + bindet stärker als ein anderes + (von links, wenn mehrere gleichberechtigt auftreten)
  • Das Assoziativgesetz gilt hier nicht
Member: nxclass
nxclass Mar 20, 2011 at 19:17:23 (UTC)
Goto Top
Vielen Dank - deine Beschreibung hat mir nun endlich die Augen geöffnet.

Das wäre übrigens eine nette Frage für einen Programmiertest
... der steht bei mir in kürze auch an. 'Zend PHP 5.3'