之前对于php的内部生命周期和zend引擎的线程安全机制做了一个介绍,这里这篇文章则是主要介绍php的内部变量是如何实现的。
了解了这些实现的方法之后,对于写php,尤其是进行php扩展开发感觉相当有帮助。
php是一种类型比较松散的语言,与C相比不需要在使用变量前给出类型,直接用就可以。为了实现这一点,php必须在数据类型的定义上做一些工作。
数据类型:
PHP网络编程技术详解由浅入深,全面、系统地介绍了PHP开发技术,并提供了大量实例,供读者实战演练。另外,笔者专门为本书录制了相应的配套教学视频,以帮助读者更好地学习本书内容。这些视频和书中的实例源代码一起收录于配书光盘中。本书共分4篇。第1篇是PHP准备篇,介绍了PHP的优势、开发环境及安装;第2篇是PHP基础篇,介绍了PHP中的常量与变量、运算符与表达式、流程控制以及函数;第3篇是进阶篇,介绍
386
立即学习“PHP免费学习笔记(深入)”;
最基本的类型被称为是zval或者说Zend Value,定义在Zend/zend.h头文件中。 typedef struct _zval_struct {void describe_zval(zval *foo)
{
if (foo->type == IS_NULL) {
php_printf("The variable is NULL");
} else {
php_printf("The variable is of type %d", foo->type);
}
}void describe_zval(zval *foo)
{
if (Z_TYPE_P(foo) == IS_NULL) {
php_printf("The variable is NULL");
} else {
php_printf("The variable is of type %d",
Z_TYPE_P(foo));
}
}立即学习“PHP免费学习笔记(深入)”;
数据值
立即学习“PHP免费学习笔记(深入)”;
通过一些宏可以获取不同类型的zval的值: BVAL(): BooleanLVAL(): longDVAL(): double 这个函数针对三种不同的zval类型,分别利用Z_TYPE进行了类型判断。然后利用相应的值提取的宏进行取值。void display_values(zval boolzv, zval *longpzv,
zval **doubleppzv)
{
if (Z_TYPE(boolzv) == IS_BOOL) {
php_printf("The value of the boolean is: %s\n",
Z_BVAL(boolzv) ? "true" : "false");
}
if (Z_TYPE_P(longpzv) == IS_LONG) {
php_printf("The value of the long is: %ld\n",
Z_LVAL_P(longpzv));
}
if (Z_TYPE_PP(doubleppzv) == IS_DOUBLE) {
php_printf("The value of the double is: %f\n",
Z_DVAL_PP(doubleppzv));
}
}
void display_string(zval *zstr)
{
if (Z_TYPE_P(zstr) != IS_STRING) {
php_printf("The wrong datatype was passed!\n");
return;
}
PHPWRITE(Z_STRVAL_P(zstr), Z_STRLEN_P(zstr));
}立即学习“PHP免费学习笔记(深入)”;
数据创建:
立即学习“PHP免费学习笔记(深入)”;
想要创造一个变量并分配空间的malloc(sizeof(zval))在php这里并不可行。应该使用MAKE_STD_ZVAL(pzv), 它对空间的分配进行了优化,并且会自动的初始化refCount(表示这个变量被引用的次数)和is_ref(是否是强制引用)这两个性质。注意它的输入是一个指针.立即学习“PHP免费学习笔记(深入)”;
数据的存储
立即学习“PHP免费学习笔记(深入)”;
数据的存储都在符号表中。 symbol table,每当创建一个新的变量的时候,Zend都保存这个值到这个内部的数组中去。 符号表在RINIT之前创建,在RSHUTDOWN之后销毁。struct _zend_executor_globals {
...
HashTable symbol_table;
HashTable *active_symbol_table;
...
};<?php $foo = 'bar'; ?>
{
zval *fooval;
MAKE_STD_ZVAL(fooval); //首先分配空间,设置变量
ZVAL_STRING(fooval, "bar", 1); //然后赋值,创建一个copy,你不能直接操作常字符串
ZEND_SET_SYMBOL(EG(active_symbol_table), "foo", fooval); // 在符号表中注册,foo是一个label
}立即学习“PHP免费学习笔记(深入)”;
{
zval **fooval;
if (zend_hash_find(EG(active_symbol_table),
"foo", sizeof("foo"),
(void**)&fooval) == SUCCESS) {
php_printf("Got the value of $foo!");
} else {
php_printf("$foo is not defined.");
}
}立即学习“PHP免费学习笔记(深入)”;
为什么要声明一个zval ** fooval 然后还要通过&fooval并且转换为(void **)的形式?为什么要用sizeof("foo") 对第一个问题,要考虑到我们寻找的目标是一个zval*,所以要把它看作一个整体。利用这种写法可以避免编译告警。 第二个问题,使用sizeof(label)主要是为了表示字符串常量label的尾部,这里使用4也是可以的,但是通用性不够。立即学习“PHP免费学习笔记(深入)”;
以上就是php内部变量的一些介绍,为了能够区分不同的类型、设置获取变量值以及在符号表中增加和查找变量,这些知识必不可少。
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号