php内核zval类型,与基本类型的转换
zval类型可以是任意类型,在C语言里是union类型,但是在大多数情况下操作的都是指针。
关于zval结构的定义可以看一看
typedef union _zend_value {
zend_long lval;
double dval;
zend_refcounted *counted;
zend_string *str;
zend_array *arr;
zend_object *obj;
zend_resource *res;
zend_reference *ref;
zend_ast_ref *ast;
zval *zv;
void *ptr;
zend_class_entry *ce;
zend_function *func;
struct {
uint32_t w1;
uint32_t w2;
} ww;
} zend_value;
zval类型,要先初始化,比如某些值传递zval *时,不能直接传一个空的zval *指针过去,而是先初始化zval,然后用&zval形式生成zval *,例如:
//正确的操作,zval *类型,要先初始化zval然后再传递地址给zval *
zval myStr;
zval *myStr2;
ZVAL_STRING(&myStr, "我是一个字符串");
myStr2 = &myStr;
php_var_dump(myStr2,0);
//错误的操作示例
//ZVAL_类型函数,必须先初始化地址类型为zval,再传递数组
//如果直接传递zval *的指针地址,则会报错
zval *myStr3;
ZVAL_STRING(myStr3, "我是一个字符串");
php_var_dump(myStr3,0);
下面对普通类型,比如字符串,数字,整形,布尔型等转换为zval,以及zval类型转换为数字,字符串等反向操作
例子:
//一、普通类型转zval
//字符串
zval myStr;
ZVAL_STRING(&myStr, "我是一个字符串");
php_var_dump(&myStr,0);
//整数
zval myNum;
ZVAL_LONG(&myNum,100);
php_var_dump(&myNum,0);
//浮点数
zval myDouble;
ZVAL_DOUBLE(&myDouble,101.2);
php_var_dump(&myDouble,0);
//布尔型
zval myBoolT;
ZVAL_TRUE(&myBoolT);
php_var_dump(&myBoolT,0);
zval myBoolF;
ZVAL_FALSE(&myBoolF);
php_var_dump(&myBoolF,0);
//NULL
zval myNull;
ZVAL_NULL(&myNull);
php_var_dump(&myNull,0);
//资源类型
//ZVAL_RES(return_value, zend_resource *);
//zval类型转普通类型
//转char *
char *s = Z_STRVAL_P(&myStr);
php_printf("<br>字符串的值是:%s ;",s);
//转zend_string
zend_string *zs = Z_STR_P(&myStr);
php_printf("<br>字符串的值是:%s ;",ZSTR_VAL(zs));
//转long
long myLong = Z_LVAL_P(&myNum);
php_printf("<br>数字的值是:%ld ;",myLong);
//转double
double myDou = Z_DVAL_P(&myDouble);
php_printf("<br>浮点数的值是:%g ;",myDou);
//真、假,NULL,不能转换,直接判断
if(IS_TRUE==Z_TYPE(myBoolT)){ //Z_TYPE可以直接判断zval
php_printf("<br>True");
}
if(IS_FALSE==Z_TYPE_P(&myBoolF)){ //Z_TYPE_P可以判断zval *
php_printf("<br>False");
}
if(IS_NULL==Z_TYPE_P(&myNull)){
php_printf("<br>NULL");
}
一般情况下,我们使用 ZVAL_类型(zval *myZval, 数据) 函数为 zval 赋值,即把一般类型转换为zval类型
同时,我们可以使用 Z_TYPE(zval) 或者 Z_TYPE_P(zval *)判断 zval 的类型是什么,常量有IS_NULL,IS_TRUE,IS_FALSE等
类型标记 存储位置
IS_NULL none
IS_TRUE or IS_FALSE none
IS_LONG zend_long lval
IS_DOUBLE double dval
IS_STRING zend_string *str
IS_ARRAY zend_array *arr
IS_OBJECT zend_object *obj
IS_RESOURCE zend_resource *res
最后,可以使用 Z_类型VAL_P(zval *)把 zval 类型,转换为普通类型,例如 long myLongNum = Z_LVAL_P(zval *);
或者 long myLong2 = Z_LVAL(zval) 把 zval 类型转换为long类型
获取 zval 的 value 值
宏 值
Z_BVAL_P(pzv) boolean类型值
Z_LVAL_P(pzv) 获取整型类型
Z_DVAL_P(pzv) = d; 获取double类型
Z_STRLEN_P(pzv)
Z_STRVAL_P(pzv)
获取字符串长度/字符串类型
ZVAL _STRINGL(pzv, str, strlen(str), dup); 获取指定长度字符串长度/字符串类型
Z_RESVAL_P(pzv) 获取资源类型
Z_ARRVAL_P(pzv) 获取数组的 HashTable
文章作者: 朱丰华
文章链接: https://smart.52dixiaowo.com/blog/post-427.html
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。