摘要:中不同類型的變量進(jìn)行弱類型比較時(shí),有其語(yǔ)言本身比較特殊的規(guī)則。方法源碼如下操作數(shù)類型舉例結(jié)果將轉(zhuǎn)換為,進(jìn)行數(shù)字或詞匯比較源碼說明結(jié)果將字符串和資源轉(zhuǎn)換成數(shù)字,按普通數(shù)學(xué)比較源碼說明其他各類型比較規(guī)則見于源碼
PHP 中不同類型的變量進(jìn)行弱類型比較時(shí),有其語(yǔ)言本身比較特殊的規(guī)則。本文就起比較規(guī)則,就其源碼角度進(jìn)行解釋。
PHP-version:5.3
官方規(guī)則參考: PHP.net
規(guī)則解釋確定核心方法源碼位置 詞法分析通過詞法分析/語(yǔ)法分析/利用vld查看opcode,我發(fā)現(xiàn) PHP 源碼中,比較操作符實(shí)現(xiàn)的核心方法是 compare_function,位于 Zend/zend_operators.c +1376
如上圖示,通過 Zend/zend_language_scanner.l +1201 詞法分析規(guī)則,得到 == 對(duì)應(yīng)的 Token 為:T_IS_EQUAL
在 Zend/zend_language_parser.y 搜索上一步得到的 Token 值,得到語(yǔ)法分析中調(diào)用生成 opcode 的方法為:zend_do_binary_op,同時(shí)看到 == 所對(duì)應(yīng)的 opcode 為 ZEND_IS_EQUAL
opcode 對(duì)應(yīng)的調(diào)用函數(shù)實(shí)現(xiàn)于 Zend/zend_vm_execute.h 文件中,在此文件中搜索 ZEND_IS_EQUAL 得到如下的函數(shù)列表:
方法均以 ZEND_IS_EQUAL_SPEC 開頭,名字后綴受 == 兩個(gè)操作數(shù)的 zval 類型影響,具體的類型可以通過 vld 查看,如:
猜測(cè)是左操作數(shù)的類型 + 右操作數(shù)的類型。
以上圖為例,左操作數(shù)類型為 IS_CONST, 右操作數(shù)類型為 IS_CV,則對(duì)應(yīng)的處理方法應(yīng)該是:ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER
(注:這種確認(rèn) handler 的方法只是經(jīng)驗(yàn)規(guī)則,還有待源碼驗(yàn)證)
以上的推測(cè)正確與否,不影響我們接下來的判斷,因?yàn)槲覀儼l(fā)現(xiàn)這些方法都會(huì)調(diào)用同一個(gè)核心方法 compare_function,比較的規(guī)則就在這個(gè)方法中。通過看此方法源碼,比較規(guī)則一目了然。
compare_function 方法源碼如下:
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { int ret; int converted = 0; zval op1_copy, op2_copy; zval *op_free; while (1) { switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { case TYPE_PAIR(IS_LONG, IS_LONG): ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)操作數(shù)類型舉例 nullcompare_objects(op1, op2 TSRMLS_CC)); return SUCCESS; } /* break missing intentionally */ default: if (Z_TYPE_P(op1) == IS_OBJECT) { if (Z_OBJ_HT_P(op1)->get) { op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); ret = compare_function(result, op_free, op2 TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { ALLOC_INIT_ZVAL(op_free); if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) { ZVAL_LONG(result, 1); zend_free_obj_get_result(op_free TSRMLS_CC); return SUCCESS; } ret = compare_function(result, op_free, op2 TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; } } if (Z_TYPE_P(op2) == IS_OBJECT) { if (Z_OBJ_HT_P(op2)->get) { op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); ret = compare_function(result, op1, op_free TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { ALLOC_INIT_ZVAL(op_free); if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) { ZVAL_LONG(result, -1); zend_free_obj_get_result(op_free TSRMLS_CC); return SUCCESS; } ret = compare_function(result, op1, op_free TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; } else if (Z_TYPE_P(op1) == IS_OBJECT) { ZVAL_LONG(result, 1); return SUCCESS; } } if (!converted) { if (Z_TYPE_P(op1) == IS_NULL) { zendi_convert_to_boolean(op2, op2_copy, result); ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_NULL) { zendi_convert_to_boolean(op1, op1_copy, result); ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0); return SUCCESS; } else if (Z_TYPE_P(op1) == IS_BOOL) { zendi_convert_to_boolean(op2, op2_copy, result); ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); return SUCCESS; } else if (Z_TYPE_P(op2) == IS_BOOL) { zendi_convert_to_boolean(op1, op1_copy, result); ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); return SUCCESS; } else { zendi_convert_scalar_to_number(op1, op1_copy, result); zendi_convert_scalar_to_number(op2, op2_copy, result); converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { ZVAL_LONG(result, 1); return SUCCESS; } else if (Z_TYPE_P(op2)==IS_ARRAY) { ZVAL_LONG(result, -1); return SUCCESS; } else if (Z_TYPE_P(op1)==IS_OBJECT) { ZVAL_LONG(result, 1); return SUCCESS; } else if (Z_TYPE_P(op2)==IS_OBJECT) { ZVAL_LONG(result, -1); return SUCCESS; } else { ZVAL_LONG(result, 0); return FAILURE; } } } }
結(jié)果:將 NULL 轉(zhuǎn)換為 "",進(jìn)行數(shù)字或詞匯比較
源碼說明:
結(jié)果:將字符串和資源轉(zhuǎn)換成數(shù)字,按普通數(shù)學(xué)比較
源碼說明:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://hztianpu.com/yun/30689.html
摘要:我們修改上面代碼,再來看下返回值類型限制的情況運(yùn)行結(jié)果這段代碼我們額外聲明了返回值的類型為型。對(duì)函數(shù)返回值的聲明做了擴(kuò)充,可以定義其返回值為,無論是否開啟嚴(yán)格模式,只要函數(shù)中有以外的其他語(yǔ)句都會(huì)報(bào)錯(cuò)。 順風(fēng)車運(yùn)營(yíng)研發(fā)團(tuán)隊(duì) 王坤 發(fā)表至21CTO公眾號(hào)(https://mp.weixin.qq.com/s/ph...) showImg(https://segmentfault.c...
摘要:當(dāng)活動(dòng)線程核心線程非核心線程達(dá)到這個(gè)數(shù)值后,后續(xù)任務(wù)將會(huì)根據(jù)來進(jìn)行拒絕策略處理。線程池工作原則當(dāng)線程池中線程數(shù)量小于則創(chuàng)建線程,并處理請(qǐng)求。當(dāng)線程池中的數(shù)量等于最大線程數(shù)時(shí)默默丟棄不能執(zhí)行的新加任務(wù),不報(bào)任何異常。 spring-cache使用記錄 spring-cache的使用記錄,坑點(diǎn)記錄以及采用的解決方案 深入分析 java 線程池的實(shí)現(xiàn)原理 在這篇文章中,作者有條不紊的將 ja...
摘要:對(duì)于函數(shù),實(shí)現(xiàn)時(shí)新建一個(gè)哈希表,將需要插入的數(shù)據(jù)先插入到中,然后再把原來的數(shù)組數(shù)據(jù)寫入到中,這樣實(shí)現(xiàn)在數(shù)組前面插入數(shù)據(jù)元素的功能。這次閱讀源碼過程中,同時(shí)也研究了中的哈希表數(shù)據(jù)結(jié)構(gòu)及一些,也給自己補(bǔ)充了一些哈希表的知識(shí)。 在PHP中,在數(shù)組中添加元素也是一種很常用的操作,分別有在數(shù)組尾部和頭部添加元素,看看PHP內(nèi)部是如何實(shí)現(xiàn)數(shù)組插入的操作。 我在github有對(duì)PHP源碼更詳細(xì)的注解...
摘要:行處理視圖文件名后綴。結(jié)語(yǔ)從源碼上看,使用了原始作為模版機(jī)制使得視圖邏輯非常簡(jiǎn)單。無非也就是把視圖進(jìn)來,用輸出緩沖把執(zhí)行結(jié)果拿到即可。此文可以轉(zhuǎn)載,但轉(zhuǎn)載前需要發(fā)郵件到進(jìn)行溝通,未溝通的均視作侵權(quán)。 前言 CI 的 View 沒有像 Laravel 等一些流行框架一樣設(shè)計(jì)的那么重,有自己的一套模版機(jī)制,CI 一直采用純天然的 PHP 模板形式,純天然的好處是不用再學(xué)習(xí)一套模板語(yǔ)言了,缺...
摘要:插入排序是穩(wěn)定的算法。所以準(zhǔn)確的說,當(dāng)數(shù)組長(zhǎng)度大于的時(shí)候,采用了快速排序和插入排序的混合排序方法。在對(duì)數(shù)組進(jìn)行了一次快速排序后,然后對(duì)兩個(gè)子集分別進(jìn)行了插入排序,最終修改數(shù)組為正確排序后的數(shù)組。 JavaScript 專題系列第二十篇,也是最后一篇,解讀 v8 排序源碼 前言 v8 是 Chrome 的 JavaScript 引擎,其中關(guān)于數(shù)組的排序完全采用了 JavaScript 實(shí)...
閱讀 3253·2021-11-22 13:54
閱讀 3730·2021-11-16 11:44
閱讀 1473·2021-09-07 10:19
閱讀 1566·2019-08-29 17:30
閱讀 3277·2019-08-29 11:33
閱讀 3615·2019-08-26 12:18
閱讀 2969·2019-08-26 11:53
閱讀 1433·2019-08-26 10:47