整形通过"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。