C编程--非局部跳转

【光之魔法—程序的时光倒流】

在这里插入图片描述

简述

非局部跳转,一个在C中极具争议的机制;
使用非局部跳转可以实现从一个函数体内跳转到另一个(事先登记过的)函数体内,而不会导致堆栈混乱;
每个函数的调用上下文可都是按照严格的顺序保存在函数堆栈中;

示例代码

C

写一个demo,思考一下下面的程序输出什么;

#include <setjmp.h>
#include <stdio.h>
jmp_buf jmp;

int startjmp() {
        longjmp(jmp,1);
        return 1;
}

int main(){
        if (setjmp(b))
                printf("go main...");
        else {
                printf("start jump...");

                startjmp();
        
        }

        return 0;
}


编译执行下:

gcc jump.c -o jump

./jump
// output

start jump...go main...

Golang

golang利用goto实现【jmp.go】:


package main 
func main(){
        var j int= 0

        label :for {
                j += 1
                println("jump:[",j,"]")
                goto label


        }
        println(" main run end ...")


}
~     

run and output:

go version
go version go1.14.12 linux/amd64
go run jmp.go
...
jump:[ 598329 ]
jump:[ 598330 ]
jump:[ 598331 ]
jump:[ 598332 ]
jump:[ 598333 ]
jump:[ 598334 ]
jump:[ 598335 ]
jump:[ 598336 ]
...
// 持续输出jump

这是为啥?

总结

这是因为longjmp让程序跳转到setjmp的位置,并且将setjmp的返回设置为longjmp的第二参数值(例子中为1);所以输出start jump后输出了go main;实现了类似“时光倒流”的效果;
打个不太恰当的比喻,setjmp就是给跳转标记了位置,而longjmp就是起跳。

那么问题来了,下面这段程序输出是?

#include <setjmp.h>
#include <stdio.h>
jmp_buf jmp;

int startjmp() {
        longjmp(jmp,1);
        return 1;
}

int main(){
        int j = 1;
        if (setjmp(jmp))
                printf("go main...");
        else if (setjmp(jmp)==1){
                j += 1;
                printf(" jump:[%d] ",j);
                startjmp();

        }
        else {
                printf("start jump...");

                printf("jump return:  %d",startjmp());

        }

        return 0;
}


在这里插入图片描述
提示就这么多了【不要看错了重点(doge)】。

扩展及参考

参考阅读

1、C编程
2、非局部跳转;
3、函数堆栈;
4、程序员的自我修养;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值