整形:l、L

7.6.2.1 整形:l、L

整形通过"l"、"L"标识,表示解析的参数为整形,解析到的变量类型必须是zend_long,不能解析其它类型,如果输入的参数不是整形将按照类型转换规则将其转为整形:

zend_long   lval;
if(zend_parse_parameters(ZEND_NUM_ARGS(), "l", &lval){
    ...
}
printf("lval:%d\n", lval);

如果在标识符后加"!",即:"l!"、"L!",则必须再提供一个zend_bool变量的地址,通过这个值可以判断传入的参数是否为NULL,如果为NULL则将要解析到的zend_long值设置为0,同时zend_bool设置为1:

zend_long   lval; //如果参数为NULL则此值被设为0
zend_bool   is_null; //如果参数为NULL则此值为1,否则为0

if(zend_parse_parameters(ZEND_NUM_ARGS(), "l!", &lval, &is_null){
    ...
}

具体的解析过程:

//zend_API.c #line:519
case 'l':
case 'L':
{
    //这里获取解析到的变量地址取的是zend_long *,所以只能解析到zend_long
    zend_long *p = va_arg(*va, zend_long *);
    zend_bool *is_null = NULL;

    //后面加"!"时check_null为1
    if (check_null) {
        is_null = va_arg(*va, zend_bool *);
    }

    if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) {
        return "integer";
    }
}

static zend_always_inline int zend_parse_arg_long(zval *arg, zend_long *dest, zend_bool *is_null, int check_null, int cap)
{
    if (check_null) {
        *is_null = 0;
    }
    if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
        //传参为整形,无需转化
        *dest = Z_LVAL_P(arg);
    } else if (check_null && Z_TYPE_P(arg) == IS_NULL) {
        //传参为NULL
        *is_null = 1;
        *dest = 0;
    } else if (cap) {
        //"L"的情况
        return zend_parse_arg_long_cap_slow(arg, dest);
    } else {
        //"l"的情况
        return zend_parse_arg_long_slow(arg, dest);
    }
    return 1;
}

> Note: "l"与"L"的区别在于,当传参不是整形且转为整形后超过了整形的大小范围时,"L"将值调整为整形的最大或最小值,而"l"将报错,比如传的参数是字符串"9223372036854775808",转整形后超过了unsigned int64的最大值:0xFFFFFFFFFFFFFFFF,"L"将解析为0xFFFFFFFFFFFFFFFF。

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3