技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3251|回复: 2
收起左侧

【C】setjmp的用法

[复制链接]

1090

主题

2609

帖子

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
237
威望
495 点
宅币
21495 个
贡献
45957 次
宅之契约
0 份
在线时间
2069 小时
注册时间
2014-1-26
发表于 2014-3-27 01:19:19 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
setjmp在C语言里用于充当一个可跨函数跳转的跳转标号(可以这么理解。)
首先你需要包含一个头文件:#include<setjmp.h>
之后就可以使用setjmp了。
方法:
jmp_buf foo;//定义一个叫foo的“标号”(注意不是真的标号)

setjmp(foo);//设置这个“标号”的位置是这一行

longjmp(foo,XX);//跳转到“标号”被设置的位置,并且让跳转后的setjmp返回XX(XX是一个int数值)
请看以下的代码实例:
[C] 纯文本查看 复制代码
#include<stdio.h>
#include<conio.h>
#include<setjmp.h>

jmp_buf g_ThisJmp;

void main(void)
{
    int value;
    char ch;

    puts("Hello World!");//卖个萌

    value=setjmp(g_ThisJmp);//后面调用longjmp(g_ThisJmp,XX);都会跳转到这一行,XX是setjmp的返回值
    printf("Value=%d\n",value);//打印数值

    ch=getch();//让用户按下一个键
    longjmp(g_ThisJmp,ch);//跳转到setjmp(g_ThisJmp)那行,并且把按键值作为setjmp(g_ThisJmp)的返回值
}
这些代码等效于
[C] 纯文本查看 复制代码
#include<stdio.h>
#include<conio.h>

void main(void)
{
    int value=0;
    char ch;

    puts("Hello World!");//卖个萌

foobar://定义一个标号
    printf("Value=%d\n",value);//打印数值

    ch=getch();//让用户按下一个键
    value=ch;
    goto foobar;//跳转到标号
}
从上面的代码看好像大家觉得setjmp比goto麻烦很多,也不容易理解。但是setjmp能实现跨函数、跨文件的跳转,而goto只能实现函数内的跳转。此外setjmp也可用于“错误处理”。
函数间的跳转示例:
[C] 纯文本查看 复制代码
#include<stdio.h>
#include<conio.h>
#include<setjmp.h>

jmp_buf g_ThisJmp;

void foo()
{
    char ch=getch();
    printf("你按下了%C\n",ch);
    longjmp(g_ThisJmp,ch);//跳转走

    puts("这行字符串不可能被打印出来除非出BUG。");
}

void main(void)
{
    int value;

    puts("Hello World!");//卖个萌

    value=setjmp(g_ThisJmp);//后面调用longjmp(g_ThisJmp,XX);都会跳转到这一行,XX是setjmp的返回值
    printf("Value=%d\n",value);//打印数值

    foo();

    puts("这行字符串不可能被打印出来除非出BUG。");
}
大家可以看出,通过setjmp你可以实现各种范围内的跳转,但是前提是你必须先调用setjmp()函数来设置你的标号的位置,然后才能用longjmp来跳转到指定的位置。下面的代码就无法执行成功:
[C] 纯文本查看 复制代码
longjmp(g_ThisJmp,0);//因为g_ThisJmp并没有被初始化,所以这行代码会引发无法预测的异常。

setjmp(g_ThisJmp);//只有初始化了g_ThisJmp才能保证longjmp成功

注意事项:
1、不要以为setjmp不会改变寄存器(针对内联汇编等的提示),当你执行了setjmp的时候,寄存器并不会被保存,longjmp跳转回来的时候并不会恢复寄存器的值。
2、不要用setjmp或longjmp在中断处理程序和普通的程序中间跳来跳去,除非你跳转到浮点异常中断的处理程序内或者从浮点异常中断的处理程序内跳出。
3、在C艹的程序里小心使用setjmp,因为setjmp不支持C艹的对象和类。如果你非要用的话也请使用C艹自带的错误处理语句(try...catch)

本帖被以下淘专辑推荐:

回复

使用道具 举报

291

主题

479

帖子

5390

积分

用户组: 真·技术宅

UID
2
精华
71
威望
168 点
宅币
4079 个
贡献
141 次
宅之契约
0 份
在线时间
693 小时
注册时间
2014-1-25
发表于 2014-3-27 08:43:24 | 显示全部楼层
以前见过,不过这个几乎不会用到,他是用来破坏函数结构的,和汇编的’例程‘一样。这个函数和变参函数用法都是c语言神奇的地方

0

主题

23

帖子

65

积分

用户组: 小·技术宅

UID
6278
精华
0
威望
2 点
宅币
38 个
贡献
0 次
宅之契约
0 份
在线时间
4 小时
注册时间
2020-9-30
发表于 2020-9-30 21:35:42 | 显示全部楼层
谢谢分享
回复

使用道具 举报

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2021-11-29 01:49 , Processed in 0.042678 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表