php内核zval类型,与基本类型的转换

zend php 类型 zval 编程技术
发布日期 2023-06-06 更新日期 2023-06-06 阅读次数 127 文章字数 2.2k

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 许可协议。

zend php 类型 zval

发表评论

相关推荐
朱丰华   |   1周前   |   sql · mysql · 字节 · 字符

mysql常用字段类型详解

44    评论    点赞
朱丰华   |   9个月前   |   php

php判断是否被iframe

246    评论    点赞
朱丰华   |   1年前   |   php

php正则表达式定界符:异常Delimiter must not be alphanumeric or backslash

201    评论    点赞
朱丰华   |   1年前   |   php · 缓存 · opcache

php 加速、提高并发opcache

223    评论    点赞
朱丰华   |   1年前   |   正则 · 表达

正则表达式,实现if...then...else

127    评论    点赞
朱丰华   |   1年前   |   变量 · mysql · sql · 用户

MySQL用户自定义变量

110    评论    点赞
朱丰华   |   1年前   |   sql · php

PHP如何使用PDO批量执行SQL?

130    评论    点赞
朱丰华   |   1年前   |   php · 字符 · 字符串

如何在 PHP 中将字符串的第一个字母转换为大写

165    评论    点赞
朱丰华   |   1年前   |   php · 字符 · 正则

php正则表达式原生字符

94    评论    点赞
朱丰华   |   1年前   |   字符 · php · 比较

PHP比较字符串大小相关函数

119    评论    点赞
朱丰华   |   1年前   |   linux · 文件

linux递归统计文件夹大小、du命令_Linux du命令:查看文件夹和文件的磁盘占用情况

207    评论    点赞
朱丰华   |   1年前   |   php

windows下编写、编译php扩展

176    评论    点赞
朱丰华   |   1年前   |   linux · php

linux下编写、编译php扩展

160    评论    点赞
朱丰华   |   1年前   |   php · 混淆 · obfuscate · git

yakpro-po混淆php代码

114    评论    点赞
朱丰华   |   1年前   |   php

php扩展编译nts的方法

96    评论    点赞
朱丰华   |   1年前   |   js · 模块 · nodejs

nodejs引入自定义模块

56    评论    点赞
朱丰华   |   1年前   |   linux · 变量 · 环境

linux查看环境变量、设置环境变量

102    评论    点赞
朱丰华   |   1年前   |   js · php · 字符 · 字符串

php json_encode对字符串转义用法

143    评论    点赞
朱丰华   |   1年前   |   php · 捕获

php Fatal error怎么捕获

136    评论    点赞
朱丰华   |   1年前   |   php · 编译

ubuntu、centos系统从源码编译指定版本php--超详细

167    评论    点赞
{{item.author_name}}   |   {{new Date(item.date*1000).log()}}   |   {{it}} ·

{{item.title}}

{{item.uv}}    评论    点赞