2015-04-01 15 views
5

Ich bin nicht in der Lage, die Auswertelogik in dem unten aufgeführten Code zu erfassen. Weiß jemand, warum PHP in diesem Fall $b und $b = $b unterschiedlich auswertet?

Ich habe eine Reihe von Fragen hier bei SO gelesen und überprüfte die PHP manual. Dabei habe ich verstanden, dass "PHP nicht (im allgemeinen Fall) angeben, in welcher Reihenfolge ein Ausdruck ausgewertet wird" und dass "das Verhalten zwischen Versionen von PHP oder abhängig von der umgebenden Code" . Ich glaube aber nicht, dass dies auf diese Situation zutrifft. Oder tut es?

Als der erste, zuzugeben, dass dies nicht Ihre alltägliche Codierung Problem sein kann, bin ich immer noch neugierig. Stolperte über das Versuchen, etwas code golfing zu tun.

$a = [[00, 01, 02, 03], 
     [10, 11, 12, 13], 
     [20, 21, 22, 23], 
     [30, 31, 32, 33]]; 

$b = 2; 
echo $a[$b][$b++], PHP_EOL; 

$b = 2; 
echo $a[$b=$b][$b++], PHP_EOL; 

Ausgang - PHP 5.5.14:

32 
22 
+0

Was php sagt ist, dass es keine Ordnung wie mathematische Reihenfolge der Operationen garantiert. Es kann in jeder aktuellen Version und in jedem System die gleiche Reihenfolge haben und genauso funktionieren. Sie sagen, dass eine Änderung in einer späteren Version das Ergebnis ändern könnte und sie werden nicht garantieren, dass es immer gleich funktioniert. –

Antwort

10

Das sieht aus wie das Beispiel in der manual verwendet für den Nachweis undefiniert Reihenfolge der Auswertung. Aus dem Handbuch:

Operator Vorrang und Assoziativität bestimmen nur, wie Ausdrücke gruppiert sind, sie geben keine Reihenfolge der Auswertung. PHP legt nicht (im allgemeinen Fall) fest, in welcher Reihenfolge ein Ausdruck ausgewertet wird und Code, der eine bestimmte Reihenfolge der Auswertung annimmt, sollte vermieden werden, da sich das Verhalten zwischen PHP-Versionen oder abhängig vom umgebenden Code ändern kann.

Hervorhebungen

Das Beispiel geben sie:

<?php 
$a = 1; 
echo $a + $a++; // may print either 2 or 3 

$i = 1; 
$array[$i] = $i++; // may set either index 1 or 2 
?> 

Sie erhalten die Ausgabe Sie sind, weil in dem ersten Beispiel der Index $b++erste bestimmt wird, während in der zweiten ist der Index $b=$b zuerst.

NB

Was warum das ist, ich ein möglicher Grund glauben durch diese Note auf der gleichen Hand-Seite erklärt:

Obwohl = hat eine niedrigere Priorität als die meisten anderen Operatoren erlaubt PHP immer noch Ausdrücke ähnlich der folgenden: if (! $ a = foo()), in diesem Fall wird der Rückgabewert von foo() in $ a gesetzt.

Ich glaube, dass sie dort ein entscheidendes letztes Wort fehlen: ersten (ohne mir die Notiz zu lesen verliere ein wenig Bedeutung).

Nach den eigenen Regeln von PHP, und, nehmen wir eine FIFO-Reihenfolge an, !$a sollte zuerst ausgewertet werden.Wenn $a derzeit null oder undefined ist, dann wird !$a gleich true (es wird ausgewertet und das Ergebnis wird weggeworfen werden). Danach wird foo() ausgewertet, und sein Rückgabewert wird $a zugewiesen (auch wenn wir annehmen, FIFO, foo() muss zuerst ausgewertet werden, wenn sein Ergebnis etwas zugewiesen werden soll). Das Ergebnis dieser Zuweisung wird von if ausgewertet und ergibt genau den entgegengesetzten Wert, den der Autor wollte.

Ich bin kein C-Experte, aber ein bisschen suchen auch mir diese answer führen, die die C90 Norm zitiert:

(C90, 6.3) „Außer wie durch die Syntax genannten oder anders erkennbaren später angegeben (für die Funktion Anruf operator(), & &, ||,:., und Komma Operatoren) die Reihenfolge der Auswertung von Unterausdrücken und die Reihenfolge, in der Nebenwirkungen stattfinden, sind beide unspecitied“

Seit PHP ist auf C gebaut, macht es Sinn, dass es einige seiner ecc erben würde Entricities.

+0

Also im Grunde ist die Verwendung von '$ b ++' und '$ b' auf der gleichen Linie wie die sprichwörtliche Schachtel Pralinen. – developerwjk

+0

@developerwjk: Haha :-P Ich behalte das im Hinterkopf. – mhall

+0

Ich dachte, PHP hätte '$ b' und' $ b = $ b' als äquivalent gesehen, als hätte man die blöde Aufgabe entfernt, aber das ist wohl nicht der Fall. – mhall