33. 数据类型转换

这里写图片描述
这里写图片描述

可用看出如果字符串链接的两个操作数如果不是字符串的话, 则调用zend_make_printable_zval函数将操作数转换为"printable_zval"也就是字符串。

ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
{
    if (Z_TYPE_P(expr)==IS_STRING) {
        *use_copy = 0;
        return;
    }
    switch (Z_TYPE_P(expr)) {
        case IS_NULL:
            Z_STRLEN_P(expr_copy) = 0;
            Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC();
            break;
        case IS_BOOL:
            if (Z_LVAL_P(expr)) {
                Z_STRLEN_P(expr_copy) = 1;
                Z_STRVAL_P(expr_copy) = estrndup("1", 1);
            } else {
                Z_STRLEN_P(expr_copy) = 0;
                Z_STRVAL_P(expr_copy) = STR_EMPTY_ALLOC();
            }
            break;
        case IS_RESOURCE:
            // ...省略
        case IS_ARRAY:
            Z_STRLEN_P(expr_copy) = sizeof("Array") - 1;
            Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy));
            break;
        case IS_OBJECT:
                // ... 省略
        case IS_DOUBLE:
            *expr_copy = *expr;
            zval_copy_ctor(expr_copy);
            zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
            break;
        default:
            *expr_copy = *expr;
            zval_copy_ctor(expr_copy);
            convert_to_string(expr_copy);
            break;
    }
    Z_TYPE_P(expr_copy) = IS_STRING;
    *use_copy = 1;
}

这里写图片描述

ZEND_API void convert_to_null(zval *op) /* {{{ */
{
    if (Z_TYPE_P(op) == IS_OBJECT) {
        if (Z_OBJ_HT_P(op)->cast_object) {
            zval *org;
            TSRMLS_FETCH();

            ALLOC_ZVAL(org);
            *org = *op;
            if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
                zval_dtor(org);
                return;
            }
            *op = *org;
            FREE_ZVAL(org);
        }
    }

    zval_dtor(op);
    Z_TYPE_P(op) = IS_NULL;
}



转换为NULL非常简单,对变量进行析构操作,然后将数据类型设为IS_NULL即可。 可能读者会好奇(unset)$aunset($a)这两者有没有关系,其实并没有关系, 前者是将变量$a的类型变为NULL,这只是一个类型的变化,而后者是将这个变量释放,释放后当前作用域内该变量就不存在了。

除了上面提到的与C语言很像,在其它语言中也经常见到的强制数据转换,PHP中有一个极具PHP特色的强制类型转换。 PHP的标准扩展中提供了两个有用的方法settype()以及gettype()方法,前者可以动态的改变变量的数据类型, gettype()方法则是返回变量的数据类型。在ext/standard/type.c文件中找到settype的实现源码:
PHP_FUNCTION(settype)
{
    zval **var;
    char *type;
    int type_len = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &var, &type, &type_len) == FAILURE) {
        return;
    }

    if (!strcasecmp(type, "integer")) {
        convert_to_long(*var);
    } else if (!strcasecmp(type, "int")) {
        convert_to_long(*var);
    } else if (!strcasecmp(type, "float")) {
        convert_to_double(*var);
    } else if (!strcasecmp(type, "double")) { /* deprecated */
        convert_to_double(*var);
    } else if (!strcasecmp(type, "string")) {
        convert_to_string(*var);
    } else if (!strcasecmp(type, "array")) {
        convert_to_array(*var);
    } else if (!strcasecmp(type, "object")) {
        convert_to_object(*var);
    } else if (!strcasecmp(type, "bool")) {
        convert_to_boolean(*var);
    } else if (!strcasecmp(type, "boolean")) {
        convert_to_boolean(*var);
    } else if (!strcasecmp(type, "null")) {
        convert_to_null(*var);
    } else if (!strcasecmp(type, "resource")) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot convert to resource type");
        RETURN_FALSE;
    } else {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type");
        RETURN_FALSE;
    }
    RETVAL_TRUE;
}


这个极具PHP特色的强制类型转换就是这个函数,而这个函数是作为一个代理方法存在, 具体的转换规则由各个类型的处理函数处理,不管是自动还是强制类型转换,最终都会调用这些内部转换方法, 这和前面的强制类型转换在本质上是一样的。

http://www.php-internals.com/book/?p=chapt03/03-07-type-cast

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值