【深度解读】你所不知道empty函数源码

本文通过实例代码和PHP内核源码分析,详细解释了empty函数如何判断变量是否为空,包括对NULL、数字0、空字符串等情况的处理,并与isset函数进行了对比,揭示了两者在判断条件上的差异。
摘要由CSDN通过智能技术生成

故事背景:某天,我在帮另一名同事合并整理代码时候,发现他做了如下操作:

<?php if (!empty($nearCitys = $nearCitys['linkList'])){

 //todo

}

?>

这么多年了,我第一次见到这样的写法,或许是自己本身没系统的学习过php的语法和特性,所以猛的一看,以为是有问题的。我的理解是:empty里面是赋值语句,按道理赋值操作一定是true的。会不会实际上程序执行时候变成了如下代码逻辑:

<?php if (!empty(true)){

 //todo

}

?>

如果是上面的代码,那empty就失去了判空的意义。当时为了确认这个问题,让同事编写了demo进行试验,发现事实上是我错了。demo如下:

运行结果如下:

通过试验,我们发现实际上变量赋值操作执行之后,empty只是对该变量进行判空,而非是赋值这个操作判空。后来晚上自己仔细回想,觉得自己是白痴了。我们都知道empty现在都是可以判断函数调用返回值了,同样会存在先调用函数,而且函数调用100%成功的问题。想到此,大概就明白了empty里其实,括号里是遵循任何php的优先级特性的。

我们优先把empty这块核心源码贴给大家:

static inline int i_zend_is_true(zval *op)
{
        int result;

        switch (Z_TYPE_P(op)) {
                case IS_NULL:
                        result = 0; //如果为NULL 返回0
                        break;
                case IS_LONG:
                case IS_BOOL:
                case IS_RESOURCE:
                        result = (Z_LVAL_P(op)?1:0); //LONG,BOOL,RESOURCE的值不为空,返回真
                        break;
                case IS_DOUBLE:
                        result = (Z_DVAL_P(op) ? 1 : 0); //浮点数的值为真 返回真
                        break;
                case IS_STRING://字符型:长度为0或者长度等于一且首地址等于0 返回假
                        if (Z_STRLEN_P(op) == 0
                                || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
                                result = 0;
                        } else {
                                result = 1;
                        }
                        break;
                case IS_ARRAY://数组:如果数组的个数大于0则为真
                        result = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
                        break;
                case IS_OBJECT://对象
                        if(IS_ZEND_STD_OBJECT(*op)) { //是OBJECT
                                TSRMLS_FETCH();

                                if (Z_OBJ_HT_P(op)->cast_object) {
                                        zval tmp;
                                        if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
                                                result = Z_LVAL(tmp);
                                                break;
                                        }
                                } else if (Z_OBJ_HT_P(op)->get) {
                                        zval *tmp = Z_OBJ_HT_P(op)->get(op TSRMLS_CC);
                                        if(Z_TYPE_P(tmp) != IS_OBJECT) {
                                                /* for safety - avoid loop */
                                                convert_to_boolean(tmp);
                                                result = Z_LVAL_P(tmp);
                                                zval_pt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值