摘要:然而實際上,這個結(jié)果反而是正確的。結(jié)論我認(rèn)為出現(xiàn)這種詭異的結(jié)果應(yīng)該算是的,同時,這也說明了此種問題不太容易被發(fā)現(xiàn)和暴露,這要求我們平常寫代碼的時候盡量使用常用的語法,和精干的語句,讓代碼和邏輯達(dá)到最佳的平衡點。
前言
之前我在面試的時候,遇到許多年輕人都聲稱自己精通php,有過許多項目經(jīng)驗等等。然而,當(dāng)真正筆試的時候,我問到
$result=1; if(-1){ $result=2; } echo $result;
中,$result最終結(jié)果的時候,許多人信誓旦旦的告訴我是1。 試想,這樣一個連基本算法都搞不清楚的人,即使有過再多的項目經(jīng)驗,你敢用嗎?
引申對于算法的一些問題,我個人一向是非常較真的,我招人的時候也是非常側(cè)重此方面,因此我對php的關(guān)注也是在這方面多些。故事得從一個知乎上的問題開始。
//第一題
//第二題
這個問題非常的有意思,也是一個大坑,許多人都算錯了,包括很多我認(rèn)識的大牛。在這里就不點名字,以免其羞愧。 然而你以為我一開始算對了嗎?我算對了第一題,第二題卻是百思不得其解。最后用調(diào)試工具一番調(diào)試才算理清頭緒。索性發(fā)出來與大家一起分享這個有意思的問題。
分析 第一題 php語言解釋這個其實非常簡單,++a這種單目運算符的運算結(jié)果還是自身。 所以
$a=1; $b=&$a; echo (++$a)+(++$a); //換種寫法就等同于 $a=1; $a=++$a; //2 $a=++$a; //3 $a=$a+$a;//3+3=6
哈,很多人肯定以為是等于5,然而這個是操作的同一個變量,等同于改變了兩次$a的值,最后相加的時候,自然就是改變后的值相加,所以等于6。
正常情況然而在php中,為了照顧人類的邏輯,默認(rèn)情況下,即使名字相同的基本類型的變量,也不會使用同一個變量地址,因此,以上代碼會被解析為
$a=1; echo (++$a)+(++$a); //換種寫法就等同于 $a=1; $a=++$a; //2 $b=++$a; //3 $a=$a+$b;//2+3=5
但是由于
$b=&$a;
的存在,使得下面的第一個$a的計算方式變成了傳統(tǒng)的c語言計算方式,所以輸出了_看起來錯誤的結(jié)果_。
然而實際上,這個結(jié)果反而是正確的。PHP中的糖語法寵壞了那些基礎(chǔ)本來不扎實的孩子,對這種加法做了特別的運算處理而已。
為什么說等于6才是正確結(jié)果呢?我們知道現(xiàn)行高級語言大多來自c語言,php也不例外,我們這里用c語言來寫一遍上述代碼,然后通過反匯編來看看機器到底是怎么執(zhí)行的。
其實無論是否注釋下面的取地址,結(jié)果都是6。 我們看匯編代碼
這里更清晰的看到a的值的變化。 即是
mov edx,dword ptr [a] ;a的值為3 add edx,dword ptr [a] ; 3+3問題二 問題發(fā)現(xiàn)
由問題一的結(jié)論來分析問題二,反而陷入了一個更大的舞曲,為什么呢?
echo (++$a)+(++$a)+(++$a); //10 /* 按照問題一的分析,此處的結(jié)果應(yīng)為 a=1+1 //2 a=a+1 //3 a=a+1 //4 a=a+a+a //12 */
然而輸出的結(jié)果卻是10.
動手實驗這里我們用一個工具phpdebug.exe來調(diào)試下看看。
可以看到的a的值的變化:
1->2->3->4
然后我們再來調(diào)試一下注釋掉
$b=&$a;
的結(jié)果。
這里在第二步的時候重新給了變量$a一個地址,實際上同是叫$a,其實他們已經(jīng)不是同一個變量了。 所以他輸出的結(jié)果為9。
實驗結(jié)果但是為什么上面的結(jié)果為10呢? 這其實是因為
$b=&$a;
這個取地址運算只起效了一句運算指令,就是只管事了第一回合,對于以后的運算,php還是用了平常的算法。 即:
$a=1; $b=&$a; echo (++$a)+(++$a)+(++$a); /* 這段實際上是 $a=++$a; //2 $a=++$a; //3 //注意了,前兩個已經(jīng)得到結(jié)果了,第三個我們用一個新的變量$c。 $c=++$a; //4 $a=$a+$a; //3+3=6 $a=$a+$c; //6+4=10 */結(jié)論
我認(rèn)為出現(xiàn)這種詭異的結(jié)果應(yīng)該算是php的bug,同時,這也說明了此種問題不太容易被發(fā)現(xiàn)和暴露,這要求我們平常寫代碼的時候盡量使用常用的語法,和精干的語句,讓代碼和邏輯達(dá)到最佳的平衡點。 此BUG我已經(jīng)反饋到php官方。
后續(xù)最新的php7中已經(jīng)修復(fù)了此bug。
修訂記錄初稿 2015-09-11
修訂 2016-05-27
修訂 2016-05-30
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/21741.html
摘要:且聽下回分解基于動態(tài)規(guī)劃策略的優(yōu)化解法參見程序員的算法趣題偷懶的算盤上一篇程序員的算法趣題同數(shù)包夾程序員的算法趣題同數(shù)包夾本系列總目錄參見程序員的算法趣題詳細(xì)分析和全解程序員的算法趣題詳細(xì)分析和全解 目錄 1. 問題描述 2. 解題分析 3. 代碼及測試 4. 后記 1. 問題描述 ??...
摘要:過去一年時間寫了多篇文章來探討了我認(rèn)為的框架最核心部分的設(shè)計思路代碼實現(xiàn)。為了大家閱讀方便,我把這些源碼學(xué)習(xí)的文章匯總到這里。數(shù)據(jù)庫算法和數(shù)據(jù)結(jié)構(gòu)這些都是編程的內(nèi)功,只有內(nèi)功深厚了才能解決遇到的復(fù)雜問題。 過去一年時間寫了20多篇文章來探討了我認(rèn)為的Larave框架最核心部分的設(shè)計思路、代碼實現(xiàn)。通過更新文章自己在軟件設(shè)計、文字表達(dá)方面都有所提高,在剛開始決定寫Laravel源碼分析地...
摘要:轉(zhuǎn)載自我的博客在眾多的新特性中,我覺得這是最神奇甚至是詭異的一個,如果有不理解這個概念的朋友,可能連它的說明都看不懂。在這個例子中操作符被重載為,操作符被重載為。再重載成操作符,以后咋跟蹤代碼。。。 轉(zhuǎn)載自我的博客:http://70.io/2014/03/php-5_6-internal-operator-overloading 在眾多php 5.6的新特性中,我覺得這是最...
摘要:最近面試他人的過程中,問了一些關(guān)于引用的知識,發(fā)現(xiàn)很多同學(xué)對這方面知之甚少,還有很多工作中基本沒有使用過。沒錢給大家發(fā)紅包,給大家推薦一家上海的好公司。對于上海的小伙伴或者想去上海的小伙伴,強烈建議去看看。 真的是變懶了,一個月一篇的節(jié)湊都很難保證了。 最近面試他人的過程中,問了一些關(guān)于PHP引用的知識,發(fā)現(xiàn)很多同學(xué)對這方面知之甚少,還有很多工作中基本沒有使用過。甚至有人告訴我要少用引...
閱讀 3350·2021-11-04 16:10
閱讀 3846·2021-09-29 09:43
閱讀 2692·2021-09-24 10:24
閱讀 3338·2021-09-01 10:46
閱讀 2503·2019-08-30 15:54
閱讀 585·2019-08-30 13:19
閱讀 3232·2019-08-29 17:19
閱讀 1049·2019-08-29 16:40