剛剛在小海格友的Blog看到一篇文章「PHP Question」,他的問題如下所述:
<?php $a = 1; $a = $a-- +1; echo $a; ?>
這時候 $a 會等於多少?
其實這種問題只要針對內部的堆疊運作去Run一次就可以得到詳解了~
不過我不曉得PHP有沒有「類似」javap這樣的工具,或是有辦法可以讓我們看到PHP內部一個個opcode處理的方式?有的話分享一下唄~ 感恩呢 ^^
所以我去下載了「php-5.2.5」原始碼~ 本來想打算從PHP的原始碼中來找答案~
可是我看了看~ 總覺得不曉得要花費多少時間~ 而且這樣實在太沒效率了~ 除非你想研究則不在此限~
不過也意外發現~ PHP的原始程式還是用了「Virtual Machine」這樣的字眼 ^^~
P.S. PHP全部的opcode都定義在「Zend/zend_vm_opcodes.h」 <== 檔名有「vm」
Java解釋
這裡我打算換個角度來解釋~ 乾脆用Java來模擬一樣的問題~ 程式如下:
public class Plus { public static void main(String arg[]) { int a = 1; a = a-- + 1; System.out.println(a); } }
接著我用「javap」來反組譯一下~ 看看operand stack是怎麼Run的~
我們就直接來看上圖所用黃色框起來的opcode~
0: iconst_1 #將int constant「1」推入到Operand Stack。
1: istore_1 #將Operand Stack的「1」存到Local Variable[1]的位置(所以到這邊已經完成了「int a = 1;」)。
2: iload_1 #將剛剛那個Local Variable[1]的整數值再載入到Operand Stack。
3: iinc 1, -1 #將目前Local Variable[1]的值「減1」。
6: iconst_1 #將int constant「1」推入到Operand Stack (所以現在Operand Stack有兩個都為「1」的值)。
7: iadd #將Operand Stack前兩個整數值相加後再推入到Operand Stack (所以目前Operand Stack只有一個「2」的整數值)。
8: istore_1 #將Operand Stack「2」存到Local Variable[1]的位置。
結果出來了~ 重點就在於「3: iinc 1, -1」是減掉Local Variable[1]的值~ 而不是減掉Operand Stack中待會要進行「iadd」相加的值~,所以這個範例會印出的值當然就是「2」嚕~ ^^
呃... 又2點多了~ 來去睡~ 這個三月挺忙的 ^^a
對於這樣的結果 我不是很明白
減掉Local Variable[1]的值就是說變數a還會在得到一次「1」的值嘛?
2008-03-05 09:49:53
嗯~ 應該說執行到「8: istore_1」步驟時,會將先前所執行到「iadd」步驟的「2」整數值再覆蓋掉原先中Local Variable[1]的位置。
建議你可以拿紙筆推論一次~ 就會比較清楚! ^^
2008-03-05 20:54:31