58-定义函数的过程
58-定义函数的过程
在PHP中,用户函数的定义从function关键字开始。如下所示简单示例:
<code>function foo($var) { echo $var; } </code>
这是一个非常简单的函数,它所实现的功能是定义一个函数,函数有一个参数,函数的内容是在标准输出端输出传递给它的参数变量的值。
函数的一切从function开始。我们从function开始函数定义的探索之旅。
词法分析
在 Zend/zend_language_scanner.l中我们找到如下所示的代码:
<code>"function" { return T_FUNCTION; } </code>
它所表示的含义是function将会生成T_FUNCTION标记。在获取这个标记后,我们开始语法分析。
语法分析
在 Zend/zend_language_parser.y文件中找到函数的声明过程标记如下:
<code>function: T_FUNCTION { $$.u.opline_num = CG(zend_lineno); } ; is_reference: /* empty */ { $$.op_type = ZEND_RETURN_VAL; } | '&' { $$.op_type = ZEND_RETURN_REF; } ; unticked_function_declaration_statement: function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } ; </code>
关注点在 function is_reference T_STRING,表示function关键字,是否引用,函数名。
T_FUNCTION标记只是用来定位函数的声明,表示这是一个函数,而更多的工作是与这个函数相关的东西,包括参数,返回值等。
生成中间代码
语法解析后,我们看到所执行编译函数为zend_do_begin_function_declaration。在 Zend/zend_complie.c文件中找到其实现如下:
<code>void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */ { ...//省略 function_token->u.op_array = CG(active_op_array); lcname = zend_str_tolower_dup(name, name_len); orig_interactive = CG(interactive); CG(interactive) = 0; init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC); CG(interactive) = orig_interactive; ...//省略 if (is_method) { ...//省略 类方法 在后面的类章节介绍 } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_DECLARE_FUNCTION; opline->op1.op_type = IS_CONST; build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC); opline->op2.op_type = IS_CONST; opline->op2.u.constant.type = IS_STRING; opline->op2.u.constant.value.str.val = lcname; opline->op2.u.constant.value.str.len = name_len; Z_SET_REFCOUNT(opline->op2.u.constant, 1); opline->extended_value = ZEND_DECLARE_FUNCTION; zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); } } /* }}} */ </code>
生成的中间代码为 ZEND_DECLARE_FUNCTION ,根据这个中间代码及操作数对应的op_type。 我们可以找到中间代码的执行函数为 ZEND_DECLARE_FUNCTION_SPEC_HANDLER。
在生成中间代码时,可以看到已经统一了函数名全部为小写,表示函数的名称不是区分大小写的。
为验证这个实现,我们看一段代码:
<code>function T() { echo 1; } function t() { echo 2; } </code>
执行代码,可以看到屏幕上输出如下报错信息:
<code>Fatal error: Cannot redeclare t() (previously declared in ...) </code>
表示对于PHP来说T和t是同一个函数名。检验函数名是否重复,这个过程是在哪进行的呢? 下面将要介绍的函数声明中间代码的执行过程包含了这个检查过程。
执行中间代码
在 Zend/zend_vm_execute.h 文件中找到 ZEND_DECLARE_FUNCTION中间代码对应的执行函数:ZEND_DECLARE_FUNCTION_SPEC_HANDLER。 此函数只调用了函数do_bind_function。其调用代码为:
<code>do_bind_function(EX(opline), EG(function_table), 0); </code>
在这个函数中将EX(opline)所指向的函数添加到EG(function_table)中,并判断是否已经存在相同名字的函数,如果存在则报错。 EG(function_table)用来存放执行过程中全部的函数信息,相当于函数的注册表。 它的结构是一个HashTable,所以在do_bind_function函数中添加新的函数使用的是HashTable的操作函数zend_hash_add。
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i ').text(i)); }; $numbering.fadeIn(1700); }); });以上就介绍了58-定义函数的过程,包括了定义,过程方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果,其目的是封装一段可重复使用的代码,提高代码的可重用性和可维护性。

OPStack是由Optimism网络背后的开发团体OptimismCollective公布的一个开源区块链框架。它对于Ethereum和Optimism社区都是一个重要的工具。OPStack的主要目标是加强Optimism网络,提供关键的软件工具给OptimismMainnet,以及即将推出的OptimismSuperchain和其治理模型。通过提供一个面向开发者的环境,OPStack的核心思想是促进Ethereum领域的增长和创新。它为前沿发展铺平了道路,使区块链的创建更加简单。OPStac

此前Optimism官方宣布,Optimism链现已更名为OPMainnet,可能有人要问了OPMainnet是什么链?根据当前资料显示,OPMainnet是一个开源超级链,致力于以可持续方式为公共产品提供资金,众多L2链之中的一个,可与Base、ZoraNetwork、PGN、Redstone等链无缝通信,但它并不是一条单一的区块链,它代表的二十整个超级链网络。下面小编为大家详细说说这个OPMainnet,帮助大家搞懂OPMainnet网络。OPMainnet是什么链?OPMainnet是以太

PHP实现框架:ZendFramework入门教程ZendFramework是PHP开发的一种开源网站框架,目前由ZendTechnologies维护,ZendFramework采用了MVC设计模式,提供了一系列可重用的代码库,服务于实现Web2.0应用程序和Web服务。ZendFramework深受PHP开发者的欢迎和推崇,拥有广泛

如何在Zend框架中使用ACL(AccessControlList)进行权限控制导言:在一个Web应用程序中,权限控制是至关重要的一项功能。它可以确保用户只能访问其有权访问的页面和功能,并防止未经授权的访问。Zend框架提供了一种方便的方法来实现权限控制,即使用ACL(AccessControlList)组件。本文将介绍如何在Zend框架中使用ACL

在本文中,我们将了解enumerate()函数以及Python中“enumerate()”函数的用途。什么是enumerate()函数?Python的enumerate()函数接受数据集合作为参数并返回一个枚举对象。枚举对象以键值对的形式返回。key是每个item对应的索引,value是items。语法enumerate(iterable,start)参数iterable-传入的数据集合可以作为枚举对象返回,称为iterablestart-顾名思义,枚举对象的起始索引由start定义。如果我们忽

MySQL.proc表的作用和功能详解MySQL是一种流行的关系型数据库管理系统,开发者在使用MySQL时常常会涉及到存储过程(StoredProcedure)的创建和管理。而MySQL.proc表则是一个非常重要的系统表,它存储了数据库中所有的存储过程的相关信息,包括存储过程的名称、定义、参数等。在本文中,我们将详细解释MySQL.proc表的作用和功能

Vue.use函数的用法和作用Vue是一款流行的前端框架,它提供了许多有用的功能和功能。其中之一就是Vue.use函数,它可以让我们在Vue应用中使用插件。本文将介绍Vue.use函数的用法和作用,并且提供一些代码示例。Vue.use函数的基本用法非常简单,只需在Vue实例化之前调用它,并传入要使用的插件作为参数。下面是一个简单的示例://引入并使用插件
