变量改变时PHP内核做了些什么?
- 格式:doc
- 大小:35.50 KB
- 文档页数:4
php工作原理PHP 是一种通用的开源脚本语言,主要用于 web 开发。
它的工作原理如下:1. PHP 脚本:首先,开发人员编写 PHP 脚本,这些脚本包含了一系列的 PHP 代码。
这些代码可以被服务器解释执行,并生成动态的 web 页面。
2. 服务器:PHP 脚本需要在服务器上执行,因此需要一个运行 PHP 的服务器。
常用的 PHP 服务器包括 Apache、Nginx、Microsoft IIS 等。
3. 客户端请求:当用户在浏览器中访问 PHP 网页时,浏览器会发送一个HTTP 请求给服务器,请求的内容包括URL 地址、请求方法(GET、POST 等)和其他相关信息。
4. 服务器处理:服务器接收到来自客户端的请求后,会先解析URL 地址,确定要执行的 PHP 脚本,并将请求的数据传递给PHP 解释器。
5. PHP 解释器:PHP 解释器是服务器上的一个软件,它接收到服务器传递的 PHP 脚本后,会逐行解析执行脚本中的每一条 PHP 代码。
PHP 解释器可以将 PHP 脚本转化为可执行的机器码,并进行相应的操作。
6. 与数据库交互:在 PHP 脚本中,通常会涉及与数据库的交互。
PHP 支持多种数据库系统(如 MySQL、MariaDB、PostgreSQL 等),可以使用数据库相关的函数和扩展来执行数据库查询、插入、更新等操作。
7. 动态页面生成:在执行完 PHP 脚本后,PHP 解释器会根据脚本中的逻辑和数据,生成一个动态的网页。
8. 服务器响应:当 PHP 解释器生成了动态网页后,服务器将其作为 HTTP 响应发送给客户端,浏览器接收到响应后,会解析并渲染该网页。
以上是 PHP 的工作原理,通过编写 PHP 脚本、服务器解析执行、与数据库交互和动态页面生成,PHP 实现了动态网页的构建和展示。
PHP常量1.声明和使用常量常量可以理解为值不变的变量。
常量值被定义后,在脚本的其他任何地方都不能改变。
常量通常具有如下的属性:●常量区分大小写,在定义的时可以指定是否大小写敏感。
●其命名的规则和变量一样●常量的开头字母只能是字母和下划线,后面可以接任意个数的字母字符。
●默认的情况下,它的作用域是全局的,即在当前当前脚本的任何地方都可以使用。
●已定义常量的名称不能与再次定义的常量和变量的名称相同●在定义常量时,应该尽可能使用大写字符,便于阅读和识别。
●常量的名称不能以字符$开头,它们的值只能是特定类型的:整数、浮点数、字符串和布尔值。
在PHP中通常使用define()函数来定义常量;使用constant()函数动态获取常量值;使用defined()函数判断一个常量是否已经定义;使用get_defined_constants()函数获取所有当前已经定义的常量。
define()函数该函数用来定义常量语法:define(string constant_name,mixed value,case_sensitive=true)该函数有3个参数:constant_name:必选参数,常量名称,即标志符。
value:必选参数,常量的值。
Case_sensitive:可选参数,指定是否大小写敏感,设定为true,表示不敏感。
例子:测试常量<?php//了解常量//测试1:常量区分大小写//define("aaa",22);//define("AAA",26);//echo aaa;//echo "<br>";//echo AAA;//从输出结果可以看出常量是区分大小写的//测试2:在定义时指定是否大小写敏感//define("aaa",22,true);//define("AAA",26,true);//echo aaa;//echo "<br>";//echo AAA;//从输出结果可以看出在将参数Case_sensitive设定为true后,大小写为不敏感!//测试3:常量的命名//define("3ads",89);//echo 3ads;//输出:syntax error说明常量不能是数字开头//echo _ads;//输出:syntax error说明常量可以是下划线开头//define("a3_ds",89);//echo a3_ds;//输出:syntax error说明常量可以是字母开头/*** 测试4:测试使用范围-常量一旦被声明将可以在全局可见,也就是说,它们可以在函数内外使用,* 但是这仅仅限于一个页面之中(包含我们通过include和include_once)包含进来的PHP脚本,但是在其他的页面之中就不能使用了。
数据分析中的变量分类数据分析中的变量分类数据分析⼯作每天要⾯对各种各样的数据,每种数据都有其特定的含义、使⽤范围和分析⽅法,同⼀个数据在不同环境下的意义也不⼀样,因此我们想要选择正确的分析⽅法,得出正确的结论,⾸先要明确分析⽬的,并准确理解当前的数据类型及含义。
统计学中的变量指的是研究对象的特征,我们有时也称为属性,例如⾝⾼、性别等。
每个变量都有变量值,变量值就是我们分析的内容,它是没有含义的,只是⼀个参与计算的数字,所以我们主要关注变量的类型,不同的变量类型有不同的分析⽅法。
变量主要是⽤来描述事物特征,那么按照描述的粗劣,有以下两种划分⽅法:按基本描述划分【定性变量】:也称为名称变量、品质变量、分类变量,总之就是描述事物特性的变量,⽬的是将事物区分成互不相容的不同组别,变量值多为⽂字或符号,在分析时,需要转化为特定含义的数字。
定性变量可以再细分为:有序分类变量:描述事物等级或顺序,变量值可以是数值型或字符型,可以进⽽⽐较优劣,如喜欢的程度:很喜欢、⼀般、不喜欢⽆序分类变量:取值之间没有顺序差别,仅做分类,⼜可分为⼆分类变量和多分类变量⼆分类变量是指将全部数据分成两个类别,如男、⼥,对、错,阴、阳等,⼆分类变量是⼀种特殊的分类变量,有其特有的分析⽅法。
多分类变量是指两个以上类别,如⾎型分为A、B、AB、O【定量变量】:也称为数值型变量,是描述事物数字信息的变量,变量值就是数字,如长度、重量、产量、⼈⼝、速度和温度。
定量变量可以再细分连续型变量:在⼀定区间内可以任意取值,其数值是连续不断的,相邻两个数值可作⽆限分割,即可取⽆限个数值。
如⾝⾼、绳⼦的长度等。
离散型变量:值只能⽤⾃然数或整数单位计算,其数值是间断的,相邻两个数值之间不再有其他数值,这种变量的取值⼀般使⽤计数⽅法取得。
按照精确描述划分【定类变量】测量事物类别或属性,各类⽀架没有顺序或等级,实际上也就是上⾯说的⽆序分类变量,所包含的数据信息很少,只能计算频数和频率,是最低层次的⼀种变量【定序变量】测量事物之间的等级或顺序,就是上述的有序分类变量,由于它的变量值可以是数值型或字符型,并且可以反映等级之间的优劣,除了可以计算频数和频率之外,还可以计算累计频率,因此数据包含的信息多于定类变量。
php内核分析之扩展以下是精心为大家的关于php内核扩展方面的分析,欢迎阅读参考!更多内容请关注!这里阅读的php版本为PHP-7.1.0RC3,阅读代码的平台为linux。
我们研究下反射这个扩展。
反射这个扩展目录是存在在:ext/reflection。
其实里面的代码很简单。
一个.h文件,一个.c文件。
我们先看下.c文件中,会看到很多ZEND_METHODZEND_METHOD(reflection_function,getReturnType){...}对应的宏:#defineZEND_METHOD(classname,name)ZEND_NAMED_FUNCTION(ZEND_ MN(classname##_##name))#defineZEND_NAMED_FUNCTION(name)voidname(INTERNAL_FUNCTION_ PARAMETERS)#defineZEND_MN(name)zim_##name#defineINTERNAL_FUNCTION_PARAMETERSzend_execute_data*execut e_data,zval*return_value这里的##代表的是连接,展开实际上就是:voidzim_reflection_function_getReturnType(zend_execute_data *execute_data,zval*return_value)总而言之,我们这里是使用ZEND_METHOD定义了一个函数zim_reflection_function_getReturnType,那从执行代码是怎么调用到这里的呢?好吧,所以我们这里是看不到扩展的调用堆栈的。
那我们用gdb 看下调用堆栈。
写个使用反射扩展的脚本:123classB4{5publicfunctiontest():B6{78}9}1011functiongetB():B12{1314}1516$rc=newReflectionMethod('B','test');17var_dump((string)$rc->getReturnType(),$rc->getReturnType( ));1819$rc=newReflectionFunction('getB');20var_dump((string)$rc->getReturnType(),$rc->getReturnType( ));使用gdb进行打点,我们看了下getReturnType的扩展定义,里面有个在扩展代码中的函数reflection_type_factory,就使用这个打点了。
PHP底层原理相关的基本原理PHP是一种通用的开源脚本语言,特别适用于Web开发。
它被广泛用于服务器端编程,也可以嵌入到HTML中执行。
PHP的底层原理是指PHP语言的运行机制和实现方式,包括解释器、编译器、内存管理等方面。
1. 解释器PHP是一种解释型语言,它不需要编译成二进制代码,而是通过解释器直接解析执行源代码。
PHP解释器负责将源代码转换为可执行的指令序列,并逐行执行这些指令。
PHP解释器的工作流程如下: - 读取源代码文件并进行词法分析,将源代码转换为一个个标记(Token)。
- 进行语法分析,将标记组合成表达式和语句,并生成抽象语法树(AST)。
- 解释器按照顺序遍历AST,并根据每个节点的类型执行相应的操作。
2. 编译器尽管PHP是一种解释型语言,但在实际运行过程中会使用到编译技术来提高性能。
PHP编译器负责将源代码转换为中间表示形式(Intermediate Representation),这样可以减少每次执行时的解析和分析过程。
PHP编译器的工作流程如下: - 词法分析器将源代码转换为标记。
- 语法分析器将标记组合成表达式和语句,并生成AST。
- 编译器将AST转换为中间表示形式(如字节码)。
- 中间表示形式被解释器执行。
通过使用编译器,PHP可以在每次执行时跳过词法分析和语法分析的过程,提高了代码的执行效率。
3. 内存管理PHP的内存管理是指对内存的分配和释放进行有效控制,以避免内存泄漏和内存溢出等问题。
PHP使用垃圾回收机制来自动管理内存。
PHP的垃圾回收机制基于引用计数。
每个变量都有一个引用计数器,当一个变量被引用时,其引用计数加1;当一个变量不再被引用时,其引用计数减1。
当引用计数为0时,该变量占据的内存会被释放。
除了引用计数外,PHP还使用了循环垃圾回收机制来处理循环引用导致的无法回收的对象。
循环垃圾回收机制通过检测对象之间的关联关系来判断是否存在循环引用,并进行相应处理。
var的变量提升的底层原理是什么变量提升是 JavaScript 中一个重要概念,它指的是在代码执行之前,JavaScript 引擎会将变量的声明阶段提升至作用域顶部,也就是说,不论变量是在哪里声明的,都会被提升至作用域的顶部。
底层原理:在 JavaScript 引擎解释执行代码之前,会经历两个阶段:编译阶段和执行阶段。
在编译阶段,JavaScript 解释器会对代码进行词法分析和语法分析,然后生成一个称为“执行上下文”的内部数据结构,用来存储代码的执行环境。
在执行上下文中,会包含变量对象(Variable Object),它用来存储变量和函数的声明。
在编译阶段,当解释器遇到变量声明(使用 var 关键字)时,会将这个声明的变量添加到变量对象中,并将其初始值设置为 undefined。
这个过程被称为“变量提升”。
变量提升的过程分为两个步骤:1.声明阶段:将变量的声明添加到变量对象中,但不会赋值。
2. 初始化阶段:将变量的值赋予声明的初始值,默认为 undefined。
具体的示例代码如下:console.log(a); // undefinedvar a = 10;在上面的代码中,变量 a 被声明在 console.log(a) 之后,但在执行 console.log(a) 时,并不会报错,而是输出 undefined。
这是因为在编译阶段,JavaScript 引擎会将变量 a 的声明提升至作用域的顶部,相当于以下代码:var a;console.log(a); // undefineda=10;这就是变量提升的底层原理。
在实际执行代码时,JavaScript 引擎会按照代码的顺序执行,所以变量 a 的值会在执行 console.log(a) 之前被赋予初始值 undefined。
需要注意的是,只有变量声明会被提升,而不包括变量的赋值。
例如:console.log(b); // ReferenceError: b is not definedb=10;在上面的代码中,因为变量 b 没有被声明,所以在使用console.log(b) 输出时会报未定义(ReferenceError)。
php 底层原理
PHP是一种通用的脚本语言,用于开发动态Web应用程序。
它的底层原理是通过解释器将PHP代码转化为可执行的机器语言。
PHP的解释器是一种软件,可以将写好的PHP代码逐行解释并执行。
在执行过程中,PHP解释器会首先将PHP代码分词,将代码分解成一个个的单词或符号,然后进行语法分析和解析。
解析得到的抽象语法树将被转换成指令序列,并与PHP的内置函数库进行链接,形成可以执行的代码。
PHP的底层运行依赖于服务器端环境,通常与Web服务器(如Apache、Nginx等)配合使用。
当用户访问PHP文件时,Web服务器会将请求发送给PHP解释器。
解释器会读取相应的PHP文件,执行其中的代码,并输出生成的HTML或其他数据给Web服务器返回给用户。
PHP底层的工作原理还涉及到数据的处理。
PHP可以与各种数据库进行交互,通过数据库扩展模块实现与数据库的连接和查询操作。
PHP还支持对文件的读写、网络通信等操作,通过相关的内置函数实现这些功能。
另外,PHP还提供了丰富的功能和特性,如面向对象编程、异常处理、会话管理等。
这些功能都是建立在PHP底层的原理和解释器的基础之上。
总而言之,PHP的底层原理是通过解释器将PHP代码转化为可执行的机器语言,与Web服务器配合运行,实现动态Web应用程序的开发。
通过与数据库和其他系统的交互,实现数据处理和操作。
它的底
层工作原理是实现PHP语言的编译与解释执行,以及与服务器环境的互动。
PHP代码讲解一、什么是PHPPHP(全称:Hypertext Preprocessor,即超文本预处理器)是一种通用开源脚本语言,特别适用于Web开发。
它可以嵌入到HTML中,以动态生成内容。
PHP代码可以在服务器上执行,生成动态网页,并将其发送到客户端浏览器。
PHP还可以通过命令行运行,用于处理脚本任务。
二、PHP的基本语法2.1 变量PHP中的变量使用$符号作为前缀,可以存储各种类型的数据,如整数、浮点数、字符串、数组等。
变量在使用前不需要声明类型。
$age = 25;$name = "John Doe";$grades = [80, 90, 75, 85];2.2 控制结构PHP支持常见的控制结构,如条件语句、循环语句和跳转语句。
2.2.1 条件语句条件语句用于根据条件的真假执行不同的代码块。
if ($age > 18) {echo "You are an adult.";} elseif ($age > 12) {echo "You are a teenager.";} else {echo "You are a child.";}2.2.2 循环语句循环语句用于重复执行一段代码。
for ($i = 0; $i < 5; $i++) {echo $i;}while ($i < 10) {echo $i;$i++;}foreach ($grades as $grade) {echo $grade;}2.2.3 跳转语句跳转语句用于改变代码的执行流程。
break; // 终止当前循环continue; // 跳过本次循环迭代return; // 结束函数执行,并返回值2.3 函数函数是一段封装了特定功能的可重用代码块。
PHP提供了许多内置函数,也可以自定义函数。
function greet($name) {echo "Hello, " . $name . "!";}greet("John");三、PHP的高级特性3.1 面向对象编程PHP支持面向对象编程(OOP),可以使用类、对象、继承、封装等概念。
php-fpm的工作原理php-fpm(FastCGI Process Manager)是一个用于处理php脚本的FastCGI进程管理器。
它是PHP官方提供的一种替代传统CGI方式运行PHP的解决方案。
php-fpm的工作原理可以简单归纳为接收请求、解析请求、执行脚本、返回结果这几个步骤。
当Web服务器(如Nginx)收到一个PHP请求时,会将请求转发给php-fpm进程。
php-fpm会接收到这个请求,并进行解析。
在解析请求之前,php-fpm会首先根据配置文件中的设置,创建一定数量的子进程或线程,这些子进程或线程将用于处理具体的请求。
接下来,php-fpm会解析请求的头部信息,包括请求方法、URL、Cookie等。
然后,它会根据配置文件中的设置,确定请求应该由哪个PHP脚本来处理。
这个过程可以通过解析nginx的配置文件中的location指令来完成。
一旦确定了要执行的PHP脚本,php-fpm会将请求信息传递给PHP 解释器。
PHP解释器会将PHP脚本编译成可执行的字节码,并在内存中创建相应的数据结构,包括符号表、函数表等。
然后,PHP解释器会按照顺序执行PHP脚本中的指令,处理各种逻辑和业务逻辑。
在执行过程中,php-fpm会根据配置文件中的设置,对PHP脚本的执行进行一定的限制和控制。
例如,可以配置最大执行时间、内存限制等。
如果PHP脚本执行超时或者超过了内存限制,php-fpm会终止这个脚本的执行,并返回相应的错误信息。
当PHP脚本执行完成后,php-fpm会将执行结果返回给Web服务器。
Web服务器将根据php-fpm返回的结果,生成相应的HTTP响应,并将结果返回给客户端。
需要注意的是,php-fpm的工作原理中有一些关键的概念,如进程管理、请求解析、脚本执行等。
这些概念在实际应用中非常重要,对于理解php-fpm的工作原理和性能优化都有着重要的作用。
总结起来,php-fpm作为一种FastCGI进程管理器,负责接收、解析、执行PHP脚本,并返回执行结果。
PHP的变量是什么PHP的变量是什么PHP中的每个变量都有一个针对它的作用域,它是指可以在其中访问变量(从而访问它的值)的一个领域。
对于初学者来说,变量的作用域是它们所驻留的页面。
我们为大家收集整理了关于PHP的变量,以方便大家参考。
PHP的变量是什么1变量是程序中或以变化的量,用于存储数字、字符串或函数的结果。
一旦设置了某个变量,我们就可以在脚本中重复地使用它。
PHP 中的所有变量都是以 $ 符号开始的。
在 PHP 中设置变量的正确方法是:$var_name = value;PHP 的入门者往往会忘记在变量的前面的 $ 符号。
如果那样做的话,变量将是无效的。
下面我们创建一个存有字符串的变量,和一个存有数值的变量:$txt = "Hello World!";$number = 16;PHP 是一门松散类型的语言(Loosely Typed Language)在 PHP 中,不需要在使用变量之前先声明该变量。
在上面的例子中,您看到了,不必向 PHP 声明该变量的数据类型。
根据变量被设置的方式,PHP 会自动地把变量转换为正确的数据类型。
在强类型的编程语言中,您必须在使用前声明变量的类型和名称。
在PHP中,变量会在使用时被自动声明。
变量的命名规则变量名必须以字母或下划线 "_" 开头。
变量名只能包含字母数字字符以及下划线。
变量名不能包含空格。
如果变量名由多个单词组成,那么应该使用下划线进行分隔(比如$my_string),或者以大写字母开头(比如 $myString)。
PHP的变量是什么2变量是存储信息的容器:实例<?php$x=5;$y=6;$z=$x+$y;echo $z;>类似代数x=5y=6z=x+y在代数中我们使用字母(比如 x)来保存值(比如 5)。
从上面的表达式 z=x+y,我们能够计算出 z 的值是 11。
在 PHP 中,这三个字母被称为变量。
变量改变时PHP内核做了些什么?
看下面的内容之前先对zval这个结构体做个了解
typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;
zval结构体中共有4个元素,value是一个联合体,用来真正的存储zval的值,refcount用来计数该zval被多少个变量使用,type表示zval所存储的数据类型,is_ref用来标志该zval 是否被引用。
引用计数
<?php
$a = 'Hello World';
$b = $a;
unset($a);
?>
我们一起来剖析下上面这段代码:
$a = 'Hello World';首先这句代码被执行,内核创建一个变量,并分配12字节的内存去存储字符串'Hello World'和末尾的NULL。
$b = $a;接着执行这句代码,执行这句的时候内核里面发生了什么呢?
对$a所指向的zval中的refcount进行加1操作。
将变量$b指向$a所指向的zval。
在内核中大概是这样的,其中active_symbol_table是当前的变量符号表
{
zval *helloval;
MAKE_STD_ZV AL(helloval);
ZVAL_STRING(helloval, "Hello World", 1);
zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),
&helloval, sizeof(zval*), NULL);
ZVAL_ADDREF(helloval);
zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),
&helloval, sizeof(zval*), NULL);
}
unset($a);这句代码执行后,内核会将a对应的zval结构体中的refcount计数减一,b还和原来一样
写时复制
<?php
$a = 1;
$b = $a;
$b += 5;
?>
上面这段代码执行完之后,一般肯定希望$a=1,$b=6,但是如果像引用计数那样,$a和$b指向相同的zval,修改$b之后$a不是也变了?
这个具体是怎么实现的呢,我们一起来看下:
$a = 1;内核创建一个zval,并分配4个字节存储数字1。
$b = $a;这一步和引用计数中的第二步一样,将$b指向和$a相同的zval,并将zval中的引用计数值refcount加1。
$b += 5;关键是这一步,这一步骤发生了什么呢,怎么确保修改之后不影响$a。
其实Zend内核在改变zval之前都会去进行get_var_and_separete操作,如果recfount>1,就需要分离就创建新的zval返回,否则直接返回变量所指向的zval,下面看看如何分离产生新的zval。
复制一个和$b所指向zval一样的zval。
将$b所指向的zval中的refcount计数减1。
初始化生成的新zval,设置refcount=1,is_ref=0。
让$b指向新生成的zval。
对新生成的zval进行操作,这就是写时复制。
下面看看内核中分离时的主要代码:
zval *get_var_and_separate(char *varname, int varname_len TSRMLS_DC)
{
zval **varval, *varcopy;
if (zend_hash_find(EG (active_symbol_table),
varname, varname_len + 1, (void**)&varval) == FAILURE) { /* Variable doesn't actually exist fail out */
return NULL;
}
if ((*varval)->is_ref || (*varval)->refcount < 2) {
/* varname is the only actual reference,
* or it's a full reference to other variables
* either way: no separating to be done
*/
return *varval;
}
/* Otherwise, make a copy of the zval* value */
MAKE_STD_ZV AL(varcopy);
varcopy = *varval;
/* Duplicate any allocated structures within the zval* */
zval_copy_ctor(varcopy);
/* Remove the old version of varname
* This will decrease the refcount of varval in the process
*/
zend_hash_del(EG(active_symbol_table), varname, varname_len + 1);
/* Initialize the reference count of the
* newly created value and attach it to
* the varname variable
*/
varcopy->refcount = 1;
varcopy->is_ref = 0;
zend_hash_add(EG(active_symbol_table), varname, varname_len + 1,
&varcopy, sizeof(zval*), NULL);
/* Return the new zval* */
return varcopy;
}
写时改变
<?php
$a = 1;
$b = &$a;
$b += 5;
?>
上面这段代码执行完之后一般希望是:$a == $b == 6。
这个又是怎么实现的呢?
$a = 1;这一步骤和写时复制中的第一步一样。
$b = &$a;这一步骤内核会将$b指向$a所指向的zval,将zval中的refcount加1,并将zval 中的is_ref置为1。
$b += 5;这一步骤和写时复制中的第三步骤一样,但是内核中发生的事情却不一样。
内核看到$b进行变化的时候,也会执行 get_var_and_separate函数,看是否需要分离。
如果(*varval)->is_ref的话也会直接返回$b所指向的zval,不去分离产生新的zval,不管zval 的refcount是否>1。
这时候再去修改$b值,$a的值也就改变了,因为他们指向相同的zval。
分离的问题
说道现在聪明的你可能已经看出点问题了,如果一个zval结构体既有refcount计数又有is_ref 引用这个时候怎么办?
<?php
$a = 1;
$b = $a;
$c = &$a;
?>
如果出现上面这种情况的时候,如果$a、$b、$c指向同一个zval结构体,进行改变的时候
Zend到底去听谁的?其实这个地方不会指向同一个zval了。
如果对一个is_ref = 0 && refcount >1的zval进行写时改变这种赋值形式(就是引用赋值)的时候,Zend会将等号右边的变量分离出来一个新的zval,
对这个zval进行初始化,对之前的zval的refcount进行减1操作,让等号左边的变量指向这个新的zval,refcount进行加1操作,is_ref=1。
看看下面这张图片
<?php
$a = 1;
$b = &$a;
$c = $a;
?>
上面这又是另外一种情况,在is_ref = 1的情况下,试图单纯的进行refcount+1操作的时候会分离出来一个新的zval给等号左边的变量,并初始化他,看看下面这张图片。