0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言中的longjump和setjump函数

Q4MP_gh_c472c21 来源:CSDN博客最后一个bug 作者:CSDN博客最后一个 2022-03-30 15:00 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

相信大家看到这个标题,可能已经猜到本文要谈的话题了。没错,今天给大家介绍一种比goto还要“任性”的跳转方式,那就是C函数库中的如下两个函数:

	

1//所需头文件 2#include 3 4intsetjump(jmp_bufbuf) 5voidlongjump(jmp_bufbuf,inti) 6

一些朋友该说了,“我从来不用这些跳转,免得出问题”。还是一直以来的那句话,“存在即合理”~

下面,我们来看看这两个函数到底有什么可以推敲的东西。

1函数介绍

有研究过RTOS的朋友应该对此不难理解,setjump主要是保存当前函数调用点的现场环境(或者叫上下文),比如各种寄存器、堆栈等等,那么这些环境信息就记录在jmp_buf所定义的buf中。

而当我们在其他位置调用longjump函数就相当于一个长跳转,传入之前保存在buf中的信息,即可跳回到之前setjump所调用的位置(理解为恢复setjump所保存的环境也是可以的)。

所以,这里值得注意的是,不要率先调用longjump,否则程序不知道飞去哪里了。

其实跟RTOS中进行任务切换有着异曲同工之妙。

你大概已经注意到setjump有一个返回值,其主要分为两种情况:

当直接调用setjump函数,则返回0;

当调用longjump跳转到setjump位置,则其返回longjump的第二个非零参数。

2跟goto有啥区别?

以前我也跟大家介绍过goto这匹野马被驯服的方式(goto关键字你不知道的"那些事"(C语言提升)),在C语言中goto只能实现函数内部的跳转,无法实现跨函数的直接跳转,比如函数嵌套多层的跳转等等。

当然,你也可以借助goto与函数返回配合完成函数之间的跳转,不过那太麻烦了,所以这两个库函数该派上用场了。

这样的跳转太过于霸道,我们还是限制一下,切不可滥用,但其为异常处理代码的模块化带来了福音,在非常多的开源库中都有实际应用。

下面给大家一个参考示例 ::


	

1#include 2#include 3 4jmp_bufmark; 5intfperr; 6voidfpcheck(void); 7 8/********************************************* 9*Function:main 10*Description:主任务函数 11*Note:(公众号:最后一个bug) 12*********************************************/ 13intmain(void) 14{ 15intjmpret; 16 17//记录异常代码与正常代码分支位置 18jmpret=setjmp(mark); 19if(jmpret==0) 20{ 21//正常用户程序运行 22 23} 24else 25{ 26//在正常用户程序运行过程中发生异常 27fpcheck(); 28} 29} 30/********************************************* 31*Function:Errorhandler 32*Description:异常中断,在正常用户程序运行过程中发生异常处理函数 33*Note:(公众号:最后一个bug) 34*********************************************/ 35voidErrorhandler(void) 36{ 37fperr=num; 38longjmp(mark,-1);//进行长跳转到异常处理 39} 40 41/********************************************* 42*Function:fpcheck 43*Description:故障处理函数 44*Note:(公众号:最后一个bug) 45*********************************************/ 46voidfpcheck(void) 47{ 48 49switch(fperr) 50{ 51caseINVALID: 52//userCode 53break; 54 55caseOVERFLOW: 56//userCode 57break; 58 59caseZERODIVIDE: 60//userCode 61break; 62default: 63break; 64} 65 66}

3局限性

这组函数除了前面介绍的注意事项,还有一个非常值得注意的点就是longjump的调用时机必须在setjump被调用的所在函数返回前。

因为setjump保存有堆栈信息等,一旦setjump的被调用的函数返回则相应的环境会被释放,导致longjump无法在恢复到setjump调用位置,可能造成程序奔溃。

最后

好了,今天就跟大家分享这么多了,这一块还有一些东西可以挖掘,后面再整理一下分享出来。如果你觉得有所收获,一定记得点个赞!

原文标题:C语言中比goto还“霸道”的跳转方式

文章出处:【微信公众号:嵌入式ARM】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5589

    浏览量

    129067
  • C语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144617
  • 函数
    +关注

    关注

    3

    文章

    4406

    浏览量

    66841
  • 跳转
    +关注

    关注

    0

    文章

    5

    浏览量

    6039

原文标题:C语言中比goto还“霸道”的跳转方式

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C语言中指针函数函数指针的概念及应用示例

    C语言中,指针函数函数指针是强大且常用的工具。它们允许我们以更灵活的方式处理函数和数据,进而扩展程序的功能。
    发表于 08-16 16:14 1835次阅读

    C语言中函数的基本知识

    函数C语言中的基本构建块之一,它允许我们将代码组织成可重用、模块化的单元。
    发表于 08-16 18:25 923次阅读

    C语言中宏定义的应用

    C语言中,宏定义是一种预处理指令,用于在代码中定义和使用常量、函数或代码片段的替代。
    发表于 08-17 15:33 1375次阅读

    C语言中atoi()函数应该怎么用?

    C语言中atoi()函数应该怎么用?
    发表于 10-14 09:10

    c语言函数指针定义,指针函数函数指针的区别

     往往,我们一提到指针函数函数指针的时候,就有很多人弄不懂。下面就由小编详细为大家介绍C语言中函数指针,指针
    发表于 11-16 15:18 3975次阅读

    单片机C语言中如何使用nop函数进行短延时的效果资料和程序说明

    单片机C语言中如何使用nop函数进行短延时的效果资料和程序说明 标准的C语言中没有空语句。但在单片机的
    发表于 03-05 11:01 10次下载
    单片机<b class='flag-5'>C</b><b class='flag-5'>语言中</b>如何使用nop<b class='flag-5'>函数</b>进行短延时的效果资料和程序说明

    剖析什么是C语言中的隐式函数声明

    「1、什么是C语言的隐式函数声明」 在C语言中函数在调用前不一定非要声明。如果没有声明,那么编
    的头像 发表于 05-25 09:38 4608次阅读
    剖析什么是<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的隐式<b class='flag-5'>函数</b>声明

    C语言怎么跳出while函数

    C语言中while函数是经常用到的,这里说一下可以跳出while函数的几种方法。
    的头像 发表于 06-17 15:40 3.9w次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>怎么跳出while<b class='flag-5'>函数</b>

    C语言中函数的创建以及使用

    下面我们来介绍一下 C 语言中一个非常重要的概念 - 函数 (function)。首先就要先给函数下一个定义,函数就是完成特定任务的独立代码
    的头像 发表于 07-06 09:38 6765次阅读

    scanf在C语言中的作用

    scanf在C语言中的作用  scanf是C语言中的输入函数,用于从标准输入设备(如键盘)读取数据,并将其存储到变量中。它是
    的头像 发表于 11-23 14:13 2886次阅读

    c语言gets函数可以输入数字吗

    C语言中的gets函数是用来读取字符串的,而不是用来读取数字的。它会读取输入的字符直到遇到换行符或者文件结束符。因此,如果你尝试使用gets函数来读取数字,是无法准确获取数字本身的。
    的头像 发表于 11-24 10:00 2322次阅读

    c语言中函数函数体用什么符号括起来

    知道函数是数学里的重要组成部分,数学中我们常见到函数的概念,但是你了解C语言中函数吗?其实函数
    的头像 发表于 11-24 15:52 1332次阅读
    <b class='flag-5'>c</b><b class='flag-5'>语言中</b><b class='flag-5'>函数</b>的<b class='flag-5'>函数</b>体用什么符号括起来

    如何给C语言中函数定义两个不同的名字?

    最近有位哥问我,如何给C语言中函数定义两个不同的名字?就是这两个名字都是指向同一个函数,同一个地址,而且两个名字都可以当做函数来用的那种。
    的头像 发表于 12-19 16:21 1423次阅读

    C语言中的socket编程基础

    数据 步骤6:关闭socket 创建socket 在C语言中,创建socket需要使用socket()函数。这个函数需要两个参数:域
    的头像 发表于 11-01 16:51 1882次阅读

    EE-128:C语言中的DSP:从C调用汇编类成员函数

    电子发烧友网站提供《EE-128:C语言中的DSP:从C调用汇编类成员函数.pdf》资料免费下载
    发表于 01-07 13:48 0次下载
    EE-128:<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的DSP:从<b class='flag-5'>C</b>调用汇编类成员<b class='flag-5'>函数</b>