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 28.03.2011 um 17:14:18 Uhr
Editierfunktion ist auch nützlich

Content-ID: 162833

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

Ausgedruckt am: 21.11.2024 um 17:11 Uhr

EvilMoe
EvilMoe 17.03.2011 um 11:45:18 Uhr
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.
Guenni
Guenni 18.03.2011 um 15:59:25 Uhr
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
dog
Lösung dog 19.03.2011 um 00:30:44 Uhr
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
Guenni
Guenni 19.03.2011 um 17:39:59 Uhr
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
dog
dog 19.03.2011 um 17:44:49 Uhr
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
nxclass
nxclass 20.03.2011 um 20:17:23 Uhr
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'