PHP变量和数据类型

编程语言可以分为三大类

1. 静态类型语言,比如:C/Java等,在静态语言类型中,类型的检查是在编译期(compile-time)确定的。

2. 动态语言类型,比如:PHP,python等各种脚本语言,这类语言中的类型是在运行时确定的。

3. 无类型语言,比如:汇编语言,汇编语言操作的是底层存储,他们对类型毫无感知。

一、变量的结构和类型

1)变量的存储结构

在官方的PHP实现内部,所有变量使用同一种数据结构(zval)来保存。 它不仅仅包含变量的值,也包含变量的类型。

在PHP中,存在8种变量类型,可以分为三类:

a. 标量类型: boolean、integer、float(double)、string

b. 复合类型: array、object

c. 特殊类型: resource、NULL

变量存储结构如下:

struct _zval_struct {
    zvalue_value value;     /* 存储变量的值 是个联合体*/
    zend_uint refcount__gc;    /*表示引用计数 默认1*/
    zend_uchar type;    /* 变量具体的类型 */
    zend_uchar is_ref__gc;    /*表示是否为引用 默认0*/};

type的值可以为: IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT和IS_RESOURCE之一。

2)变量的值存储

上面的value是个联合体,正因为是这样,才能做到弱类型,联合体如下:

typedef union _zvalue_value {    long lval;    /*boolean integer*/
    double dval;    /*float*/
    struct {        char *val;        int len;
    } str;    /*String*/
    HashTable *ht;    /* Array */
    zend_object_value obj; /*Object*/} zvalue_value;

3)哈希表(HashTable)

a. 键(key):用于操作数据的标示,例如PHP数组中的索引,或者字符串键等等。

b. 槽(slot/bucket):哈希表中用于保存数据的一个单元,也就是数据真正存放的容器。

c. 哈希函数(hash function):将key映射(map)到数据应该存放的slot所在位置的函数。

d. 哈希冲突(hash collision):哈希函数将两个不同的key映射到同一个索引的情况。

4)PHP的哈希实现

PHP的大部分的语言特性都是基于哈希表实现的, 例如:变量的作用域、函数表、类的属性、方法等,Zend引擎内部的很多数据都是保存在哈希表中的。

PHP中的哈希表是使用拉链法来解决冲突的,Zend为了保存数据之间的关系使用了双向链表来链接元素。

拉链法如下图所示:

图中,”John Smith”和”Sandra Dee” 通过哈希函数都指向了152 这个索引,该索引又指向了一个链表, 在链表中依次存储了这两个字符串。

Zend引擎哈希表结构和关系如下:

a. Bucket结构体维护了两个双向链表,pNext和pLast指针分别指向本槽位所在的链表的关系。

b. 而pListNext和pListLast指针指向的则是整个哈希表所有的数据之间的链接关系。

c. HashTable结构体中的pListHead和pListTail则维护整个哈希表的头元素指针和最后一个元素的指针。

二、常量

PHP内核会在词法解析时将这些常量的内容赋值进行替换,而不是在运行时进行分析。

1)常量的存储结构

常量是在变量的zval结构的基础上添加了一额外的元素。

typedef struct _zend_constant {
    zval value; /* zval结构,PHP内部变量的存储结构,在第一小节有说明 */
    int flags;  /* 常量的标记如 CONST_PERSISTENT | CONST_CS | CONST_CT_SUBST*/
    char *name; /* 常量名称 */
    uint name_len;  
    int module_number;  /* 模块号 */} zend_constant;

1. CONST_CS:常量大小写敏感

2. CONST_PERSISTENT:常量需要持久化;如果是非持久常量,会在RSHUTDOWN阶段就将该常量释放,否则只会在MSHUTDOWN阶段将内存释放。用户定义的常量都是非持久化的,通常扩展和内核定义的常量会设置为持久化。

3. CONST_CT_SUBST:Allow compile-time substitution(在编译时可被替换)。在PHP内核中这些常量包括:TRUE、FALSE、NULL、ZEND_THREAD_SAFE和ZEND_DEBUG_BUILD五个。

PHP常量的定义过程如下:

define(‘KFJ‘, ‘Hello World‘);

2)标准常量

PHP内置定义的常量,他们属于标准常量。如错误报告级别E_ALL, E_WARNING等。

这些常量都是持久化常量。

3)魔术常量

PHP中有七个魔术常量,他们的值其实是变化的,它们的值随着它们在代码中的位置改变而改变。 所以称他们为魔术常量。

三、预定义变量

  对于全部脚本而言,PHP 提供了大量的预定义变量。这些变量将所有的外部变量表示成内建环境变量,并且将错误信息表示成返回头。

  $_GET,$_POST,$_SERVER,$_FILES等变量,会在PHP脚本运行之前就将它们加入到HashTable数据类型的符号表中。

  由于都存储在一个地方,所以在某个局部函数中使用类似于$GLOBALS变量这样的预定义变量, 如果在此函数中有改变的它们的值的话,这些变量在其它局部函数调用时会发现也会同步变化。

四、静态变量

  通常意义上静态变量是静态分配的,他们的生命周期和程序的生命周期一样, 只有在程序退出时(RSHUTDOWN)才结束期生命周期,这和局部变量相反,局部变量只有在函数执行时才会存在。 通常,当一个函数执行完毕,它的局部变量的值就已经不存在,而且变量所占据的内存也被释放。

静态变量可以分为3中:

1)静态全局变量:PHP中的全局变量(预定义变量等)也可以理解为静态全局变量,因为除非明确unset释放,在程序运行过程中始终存在。

2)静态局部变量:也就是在函数内定义的静态变量,Zend为每个函数分配了一个私有的符号表(EG(active_op_array)->static_variables)来保存该函数的静态变量。

3)静态成员变量:这是在类中定义的静态变量,和实例变量相对应,静态成员变量属于类,不属于某个实例,所以可以在所有实例中共享。

查看在线代码

//静态局部变量function static_function() {    static $i=0;    $i++;    print_r($i);
}
static_function();//1static_function();//2static_function();//3

//静态成员变量
//Zend为每个函数分配了一个私有的符号表来保存该函数的静态变量。class static_class {    public static $i=0;    public function get_static() {        return ++self::$i;
    }
}$class1 = new static_class();$class2 = new static_class();print_r($class1->get_static());//1print_r($class2->get_static());//2

五、类型提示的实现

PHP5中引入了类型提示这个概念。在定义方法参数时,同时定义参数的对象类型。

下面的示例代码就是类型提示,但是在引用的时候传入1,就会报错。

function prompt(Array $arr) {    print_r($arr);
}
prompt(1);

类型提示的实现有2种:

1)参数声明时的类型提示,例如“$arr=[1,2];”

2)函数或方法调用时的类型提示(上面的示例代码)

六、变量的生命周期

在ZE进行词法和语法的分析之后,生成具体的opcode,这些opcode最终被execute函数解释执行。

1)变量的声明和赋值

在使用一个变量时,我们不需要声明,也不需要初始化,直接对其赋值就可以使用。

$a = 10;

当赋值的时候,zval结构中的refcount_gc默认为1,当引用这个值的时候,会加1。

$a = 10;$b = &$a;//$a和$b引用了同一个zval结构,refcount_gc变为2,is_ref_gc为1$c = $a;//$c新建了一个zvak结构,refcount_gc变为2为1

2)变量的作用域

变量按作用域类型分为:全局变量和局部变量。

与JavaScript不同,得益于闭包的特性,JavaScript可以在函数中调用函数外的变量,而PHP不行。下面的代码是错误的:

$bar = ‘outter‘;function _global() {    print_r($bar);//这里会报错}
_global();print_r($bar);//输出为outter

a. 全局变量会保存在symbol_table中, 也就是顶层作用域中的变量。

b. 函数或者对象的方法在被调用时会创建active_symbol_table来保存局部变量。

c. 函数中的静态变量存放在私有的符号表(EG(active_op_array)->static_variables)中。所以不会在函数结束的时候销毁。

3)global

global语句的作用是定义全局变量,也就是将变量放到symbol_table中。

将上面的代码修改一下,增加一个global声明:

$bar = ‘outter‘;function _global() {    global $bar ;//添加global声明
    $bar = ‘inner‘;    print_r($bar);
}
_global();print_r($bar);//输出inner

七、数据类型转换

1)隐式类型转换

a. 直接的变量赋值操作

b. 运算式结果对变量的赋值操作

$str = 33;    //integer 另外的float(double)类似var_dump(‘prase‘.$str);$str = null;    //nullvar_dump(‘prase‘.$str);$str = true;    //booleanvar_dump(‘prase‘.$str);$str = array(1,2);    //arrayvar_dump(‘prase‘.$str);$str = new static_class();    //object 调用静态变量中的类var_dump(‘prase‘.$str);

a. 隐式转换null的时候,最后输出的是空

b. boolean转换成了0或1

c. 虽然array最后输出了,但最后还是报错。

d. 而类是直接报错,没有输出。

2)显示类型转换

PHP中允许的强制类型有:

a. (int), (integer) 转换为整型

b. (bool), (boolean) 转换为布尔类型

c. (float), (double) 转换为浮点类型

d. (string) 转换为字符串

e. (array) 转换为数组

f. (object) 转换为对象

g. (unset) 转换为NULL,这个还是第一次见到

时间: 2024-09-29 15:49:35

PHP变量和数据类型的相关文章

轻松学习JavaScript五:JavaScript的变量和数据类型

对于一们编程语言,肯定包含变量和数据类型.今天我们就来看看JavaScript脚本语言的变量和数据类型.相对 于其他的Java,C++等高级程序语言,JavaScript显得很简单. 一变量 JavaScript的变量是松散类型的,所谓松散就是用来保存任何类型的数据.变量是存储信息的容器.定义变量时 要使用var操作符(var是关键字),后面跟一个变量名(变量名是标识符).变量也就是初始化后可以再次改变的量. 那么我们来看看实例: <span style="font-size:18px;&

Python之变量、数据类型、运算符

变量与数据类型 1 掌握变量使用及命名规则 1.1 变量赋值 变量赋值通过"="实现, 实例: a = 10 b = 10.11 c = 'abc' 注意事项:变量名尽量具有现实意义 实例:price = 10 Name = '张三' Age = '16' 注意事项:变量的值如果有中文则必须在文件头部声明文件编码 #coding:utf8 1.2 变量命名规则 1.2.1 一般由字母.数字.下划线组成: 实例: i.__my_name.name_21 和 a1b1_c3 1.2.2 不

Java 第二章 变量 、数据类型和运算符 笔记

Java 第二章 变量 .数据类型和运算符 一.变量:存储数据的一个基本单元. 二.变量的声明和赋值: 1)声明并赋值:数据类型 变量名=值;      例:int  price=1000; 2)声明.赋值分两步:数据类型 变量名;   例: int  price; 变量名=值;              price=1000; 三.数据类型2种: 1)基本数据类型8种: Byte 长度:-128~127(-2的7次方到2的7次方减1) Short   -2的15次方到2的15次方减1 Int

php什么是变量的数据类型

什么是变量的数据类型 在变量中,由于变量占用的空间单元不一样(占的地盘大小不一样),也分成几种数据类型,就像超市商品的包装袋,有几种不同类型,不同的商品使用不同的包装袋.我们可以通过使用“memory_get_usage”获取当前PHP消耗的内存. 任务 咱对比一下内存消耗吧! 在右边的编辑器中,咱分别定义四种不同的数据类型,分别是字符串类型,整型,浮点型和数组(后续会详细介绍这几种类型). 1.在第4行中定义字符串类型“$var_string = "123";” 2.第7行定义整型“

PHP100-第三讲 PHP5.4 语法、常量、变量、数据类型详解

内容摘要: ①PHP5.4 的基本语法与写作格式 ②PHP5.4 的变量与变量数据类型 ③PHP5.4 的系统常量与自定义常量 PHP5.4 的基本语法与写作格式: 任何程序语言都有自己的语言风格,PHP语言也有自己独特的风格,虽然也继承了许多Perl和C的语言特色.但经过多年的发展PHP已经成为了一个成熟 的编程语言,所以我们还需要认真的学习PHP的独特语法.PHP一个很大的特色就是与HTML标签语言进行混编,这种模式是今后很长一段学习过程中所用到 的格式,因此我们先来通过一个例子来认识一下P

js的变量和数据类型

1.变量 -javaScript是一种弱类型的脚本语言. -var c = 3:即变量的声明(变量使用之前必须加var声明,编程规范). -变量的命名规则 -1.变量名必须以字母或者下划线_或者$为开头. -2.变量名长度不能超过255字符. -3.变量名中不允许使用空格. -4.不适用脚本语言中保留的关键字及保留符号作为变量名. -5.变量名区分大小写.(javaScript是区分大小写的语言). -全局变量 - 在方法外部声明的变量 - 方法内部,没有加var关键字声明的变量(但是想要使用这

Java学习 (三)、变量,数据类型(一)

一.声明和使用变量的步骤: ①声明一个变量以分配空间:根据类型开辟空间. int a;  int 占4个字节 ②为变量赋值:将数据存入空间. a=20; ③使用变量:取出数据,使用. System.out.println(a); 二.标识符命名规则 变量名=首字符+其余部分 首字符:字母.下划线.’$’ 其余部分:数字.字母.下划线.’$’ 变量名:应避开关键字,如int int=10;第二个int就是关键字,不能使用 符合驼峰命名法:mySocre,若名字由多个单词组成,从第二个单词开始,首字

php变量的数据类型

一.类型 标量类型: 布尔型 整型 浮点型 字符串 复合类型:  数组  对象 特殊类型:  资源 null    1. 布尔型 true  false 以下值认为是false  其他值都认为是true; 布尔值false 整型值0 浮点的0 空字符串和字符串0 空数组 空对象(只适用于php4) 特殊类型null    2. 整型  正整数和负整数  0  整型的最大值  相对于32位操作系统 我们的最大值是 2147483647 整型的最小值  相对于32位操作系统 我们的最小值是 - 21

变量的数据类型

变量的数据类型 一个变量的类型,由变量的值来决定. 基本数据类型:字符型(String).数值型(Number).布尔型(Boolean).Undefined(未定义型).Null(空型) 复合数据类型:数组(Array).对象(Object).函数(Function) 注意:基本数据类型和复合数据类型的主要区别:基本数据类型的值只有一个,而复合数据类型的值可以多个 1.数值型数据(Number) 数值型数据包含整型和浮点型(小数). Var a = 100; Var a = 0; Var a

Java基础——变量及数据类型

每种语言中都会设计到许多数据,于是,你会接触到不同的数据类型,初次接触数据类型是也曾晕晕乎乎,在java语言中,终于有点明白了,梳理一下,与君共勉. 变量的概念 内存中的一个存储区域 变量名+数据类型 可在同一类型范围内不断变化 为什么定义变量: 用于不断的存放同一类型的常量,并可以重复使用 使用变量注意: 变量的作用范围,一对{}之间有效 初始化值 定义变量的格式: 数据类型   变量名=初始化值 eg: int x = 4 注:格式固定 理解:变量就如同数学中的未知数. 数据类型: 整数默认