成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

PHP源碼分析之等于操作符(==)

sushi / 1595人閱讀

摘要:中不同類型的變量進(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

語(yǔ)法分析


Zend/zend_language_parser.y 搜索上一步得到的 Token 值,得到語(yǔ)法分析中調(diào)用生成 opcode 的方法為:zend_do_binary_op,同時(shí)看到 == 所對(duì)應(yīng)的 opcodeZEND_IS_EQUAL

確定 zend 執(zhí)行時(shí)的函數(shù)

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)compare_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;
                }
        }
    }
}
操作數(shù)類型舉例 null

結(jié)果:將 NULL 轉(zhuǎn)換為 "",進(jìn)行數(shù)字或詞匯比較

源碼說明:

array

結(jié)果:將字符串和資源轉(zhuǎn)換成數(shù)字,按普通數(shù)學(xué)比較

源碼說明:

其他各類型比較規(guī)則見于 compare_function 源碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://hztianpu.com/yun/30689.html

相關(guān)文章

  • PHP7源碼分析PHP7到底有多快,基準(zhǔn)測(cè)試與特性分析告訴你

    摘要:我們修改上面代碼,再來看下返回值類型限制的情況運(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...

    Towers 評(píng)論0 收藏0
  • 后端ing

    摘要:當(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...

    roadtogeek 評(píng)論0 收藏0
  • [PHP源碼閱讀]array_push和array_unshift函數(shù)

    摘要:對(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ì)的注解...

    HackerShell 評(píng)論0 收藏0
  • Codeigniter 4.0-dev 版源碼學(xué)習(xí)筆記七—— View 視圖

    摘要:行處理視圖文件名后綴。結(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ǔ)言了,缺...

    LiangJ 評(píng)論0 收藏0
  • JavaScript專題解讀 v8 排序源碼

    摘要:插入排序是穩(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í)...

    princekin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<