【走进php内核】之 中断及跳转(break,continue,goto)

中断及跳转

PHP中的中断及跳转语句主要有break、continue、goto,这几种语句的实现基础都是跳转。

break与continue

break用于结束当前for、foreach、while、do-while 或者 switch 结构的执行;continue用于跳过本次循环中剩余代码,进行下一轮循环。break、continue是非常相像的,它们都可以接受一个可选数字参数来决定跳过的循环层数,两者的不同点在于break是跳到循环结束的位置,而continue是跳到循环判断条件的位置,本质在于跳转位置的不同。

break、continue的实现稍微有些复杂,下面具体介绍下其编译过程。

上一节我们已经介绍过循环语句的编译,其中在各种循环编译过程中有两个特殊操作:zend_begin_loop()、zend_end_loop(),分别在循环编译前以及编译后调用,这两步操作就是为break、continue服务的。

在每层循环编译时都会创建一个zend_brk_cont_element的结构:

typedef struct _zend_brk_cont_element {
    int start;
    int cont;
    int brk;
    int parent;
} zend_brk_cont_element;

cont记录的是当前循环判断条件opcode起始位置,brk记录的是当前循环结束的位置,parent记录的是父层循环zend_brk_cont_element结构的存储位置,也就是说多层嵌套循环会生成一个zend_brk_cont_element的链表,每层循环编译结束时更新自己的zend_brk_cont_element结构,所以break、continue的处理过程实际就是根据跳出的层级索引到那一层的zend_brk_cont_element结构,然后得到它的cont、brk进行相应的opcode跳转。

各循环的zend_brk_cont_element结构保存在zend_op_array->brk_cont_array数组中,编译各循环时依次申请一个zend_brk_cont_element,zend_op_array->last_brk_cont记录此数组第一个可用位置,每申请一个元素last_brk_cont就相应的增加1,然后将数组扩容,parent记录的就是父层循环结构在该数组中的存储位置。

zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
{
    op_array->last_brk_cont++;
    op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont);
    return &op_array->brk_cont_array[op_array->last_brk_cont-1];
}

示例:

$i = 0;
while(1){
    while(1){
        if($i > 10){
            break 2;
        }
        ++$i
    }
}

循环编译完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值