2013-01-02 20 views
8

W podręczniku PHP, operator precedence section, jest to przykład:

// mixing ++ and + produces undefined behavior 
$a = 1; 
echo ++$a + $a++; // may print 4 or 5 

rozumiem zachowanie jest niezdefiniowane powodu następującego powodu:

Od x + y = y + x tłumacz może bezpłatnie oceniać x i y w dowolnej kolejności, aby zoptymalizować prędkość i/lub pamięć. Zawarłem to po spojrzeniu na C code example in this article.

Moje pytanie brzmi, że wyjście z powyższego kodu PHP powinny być 4 bez względu na sposób ekspresji i sub-wyrażenia są oceniane:

  • OP1 = ++ $ a => $ a = 2 op1 = 2; op2 = $ a ++ => op2 = 2, $ a = 3; 2 + 2 = 4
  • op1 = $ a ++ => op1 = 1, $ a = 2; op2 = ++ $ a => op2 = 3, $ a = 3; 1 + 3 = 4

Skąd się bierze 5? Czy powinienem dowiedzieć się więcej o tym, jak działają operatorzy?

Edit:

I zostały patrząc na Incrementing/Decrementing Operators sekcji, ale wciąż nie może zrozumieć, dlaczego 5.

++ $ a: preinkrementuj - Przyrosty $ ao jeden, następnie zwraca $ a.
$ a ++: Post-increment - zwraca $ a, następnie zwiększa się o jeden.

+0

Czy naprawdę wydrukowano 5 podczas uruchamiania tego kodu? – Ranty

+0

Nie. Zawsze miałem 4 wersje PHP. Jest to słowo _may_, oznacza to, że mogę uruchomić ten kod milion razy, uzyskując reesult 4, ale nie ma _gwarancji_. –

+0

@ H2CO3: Jestem bardziej zainteresowany poznaniem _dlaczego 5_. –

Odpowiedz

5
a = 1; 
++ (preincrement) gives a = 2 (higher precedence than +, and LR higher precedence than postincrement) 
++ (postincrement) gives a = 3 (higher precedence than +) 
+ (add) gives 2 + 3 = 5 

$ a jest początkowo ustawiona na 1. ++ $ a następnie preincrements $ a przed użyciem go w formule, ustawienie go na 2, i popychając tę ​​wartość na stosie Lexer. Następnie wykonywany jest kod $ ++, ponieważ inkrementator ma wyższy priorytet niż +, a wartość ta jest również przekazywana do stosu lekserów; a dodawanie, które następnie następuje, dodaje wynik 2 stosu lekserów do wyniku 3 stosu leksera, dając wynik 5, który jest następnie odbijany. Wartość $ raz linia wykonała to 3.

LUB

a = 1; 
++ (preincrement) gives a = 2 (higher precedence than +, and LR higher precedence than postincrement) 
+ (add) gives 2 + 2 = 4 (the value that is echoed) 
++ (postincrement) gives a = 3 (incremented __after__ the variable is echoed) 

$ a jest wstępnie ustawiony na 1. Gdy formuła jest parsowań że ++ $ a preincrements $ a, ustawienie go na 2 przed użyciem w formule (przesunięcie wyniku do stosu lekserów). Wynik ze stosu lekserów i bieżąca wartość $ a są następnie dodawane razem dając 4; i ta wartość jest echem. Ostatecznie, $ a jest postinkrementowane, pozostawiając wartość 3 w $ a.

+2

Edytowałem moje pytanie. Myślałem o tym również, ale później zdałem sobie sprawę, że przyrost post zwróci bieżącą wartość (tj. 2), _then_ inkrementuje a. –

1

Tak, to daje 5, ponieważ operator prawostronny działa najpierw przez jego priorytet/precendence, a następnie operator sumy (+) będzie działać. Więc najpierw przyrost sprawia, że ​​do 2, a drugi sprawia, że ​​do 3, a po tym jak będzie podsumować i wyjść ci wynik jako 5

$result = ++$a + $a++; 

++$a wyjścia jak 2

$a++ wyjść jak 2 3 tylko ale wewnętrznie będzie on zwiększany.

ostatecznie suma wola się stanie jak 2 + 3 = 5

+2

"Tak, da ci 5" - raczej "Tak, może ci też dać 5". –

+0

Nawet jeśli $ a wynosi 3 po oszacowaniu wartości $ a ++, wyrażenie $ a ++ nadal daje wartość 2, więc suma wynosi 2 + 2. – fgb

0

Mark, Wierzę, że jesteś w błędzie!

Post-inkrementacja: zwraca $ a, a następnie zwiększa o jeden. (z dokumentacji)

Tak więc nie ma sposobu na uzyskanie wartości $ 3 w operacjach sumy.

+0

Chodzi o to, że wynik jest nieprzewidywalny: OP pytał, jak można uzyskać wynik 5, nie, czy dało wynik 5 –

+0

Ale potem wyjaśnienie: "++ $ a daje 0, a $ a ++ daje 5, więc 0 + 5 = 5 "dałby ten sam wysiłek. Obaj są przeciwko dokumentacji. – TomTom

Powiązane problemy