在C中有时我们会使用goto语句用于运行跳转,可是不能跨越函数

#include <stdio.h>

void func2()
{
int num = 0;
dst2:
if (num > 0)
{
printf("func1()\n");
func3();
}
if (num == 1)
return;
num++;
goto dst2;
} void func3()
{
} void func1()
{
dst1:
func2();
goto dst2;//error
} int main()
{
func1();
return 0;
}

而在深层嵌套函数中的跳转,能够使用setjmp和longjmp函数。

这两个函数对于处理发生在深层嵌套函数中出错的情况是很实用的。

函数原型:

#include <setjmp.h>
int setjmp(jmp_buf env);
返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
void longjmp(jmp_buf env, int val);

參数说明:

setjmp的env參数的类型是一个特殊类型jmp_buf,这一数据类型是某种形式的数组,当中存放存放在调用longjmp时能用来恢复栈状态的全部信息

longjmp的env參数指定恢复栈到某个状态,val为非0值,使用第二个參数的原因是对于一个setjmp能够有多个longjmp。比如。在func2()中以val为2调用longjmp,

func3()以val3调用longjmp,调用longjmp导致程序跳转到对应的指定env处的setjmp.并导致setjmp返回val值。通过測试返回值可推断造成返回的longjmp是在func2()中还是func3()中

实例:

#include <stdio.h>
#include <setjmp.h> jmp_buf jmpbuffer;
int times = 0; void func3()
{
times++;
longjmp(jmpbuffer, 3);
} void func2()
{
func3();
} void func1()
{
int r;
r = setjmp(jmpbuffer);
printf("%d\n", r);
if (times == 1)
return;
func2();
} int main()
{
func1();
return 0;
}

longjmp跳转对变量的影响

longjmp实际上恢复栈的状态。所以我们能够猜測,对于全局变量和静态变量。不存储在栈区中,所以值不会受影响,而大多数实现不会回滚自己主动变量的值

若不希望自己主动变量的值被回滚,能够指定其具有volatile属性。

很多其它关于volatile见  http://blog.csdn.net/aspnet_lyc/article/details/17231989

实例:

#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h> jmp_buf jmpbuffer; void func1()
{
int auto_data = 0;
static int static_data = 0;
volatile int volatile_data = 0; if (setjmp(jmpbuffer) != 0)
{
printf("after jmp:\n");
printf("auto: %d\n", auto_data);
printf("static: %d\n", static_data);
printf("volatile: %d\n", volatile_data);
exit(0);
}
printf("auto: %d\n", auto_data);
printf("static: %d\n", static_data);
printf("volatile: %d\n", volatile_data); auto_data++;
static_data++;
volatile_data++;
longjmp(jmpbuffer, 3);
} int main()
{
func1();
return 0;
}

以不带优化和带优化选项对此程序部分进行编译,运行结果:

不带优化编译gcc

带优化编译 gcc -O

存放在存储器中的变量将具有longjmp时的值,而在cpu寄存器中的变量则恢复为调用setjmp时的值。

不进行优化时,自己主动变量存放在存储器中。

优化后,自己主动变量存放寄存器中,这就是优化编译后auto_data值变为0的原因。

setjmp与longjmp的更多相关文章

  1. C 语言中 setjmp 和 longjmp

    在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...

  2. 非本地跳转之setjmp与longjmp

    非本地跳转(unlocal jump)是与本地跳转相对应的一个概念. 本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上.然而,本地跳转不能将控制权转移到 ...

  3. setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto

    目录 . 应用场景 . Use Case Code Analysis . 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Over ...

  4. C中的setjmp与longjmp

    setjmp与longjmp是属于C语言中的,当然,C++也会有这两个函数了.他们的原型如下: int setjmp( jmp_buf env ); 作用:第一次调佣时,将寄存器的当前状态信息全部存入 ...

  5. setjmp 与 longjmp

    setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理. 先来看一下这两个函数的定义 ...

  6. setjmp和longjmp的使用

    问题描述:          setjmp和longjmp的使用 问题解决:       setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序 ...

  7. 【转】浅析C语言的非局部跳转:setjmp和longjmp

    转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...

  8. 【转载】setjmp和longjmp函数使用详解

    [说明]本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322 --------------- ...

  9. 进程环境之setjmp和longjmp函数

    在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp.这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的. setjmp和longjmp函数也称为 ...

  10. setjmp和longjmp函数使用详解

    源地址:http://blog.csdn.net/zhuanshenweiliu/article/details/41961975 非局部跳转语句---setjmp和longjmp函数.非局部指的是, ...

随机推荐

  1. JZYZOJ1390【noi2001】炮兵阵地 状压DP

    http://172.20.6.3/Problem_Show.asp?id=1390 需要储存该行和上一行两个状态.通过观察规则可以发现条件允许的状态很少(相邻两个至少空两格),据此可以减少状态数量, ...

  2. BZOJ 3289 Mato的文件管理(莫队+树状数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3289 [题目大意] 求静态区间逆序对. [题解] 我们对查询进行莫队操作,对于区间的删 ...

  3. BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1934 [题目大意] 每个人对于投票都有自己原来的观点:1或者0, 他可以违背自己原来的 ...

  4. BZOJ 1229 [USACO2008 Nov]toy 玩具(三分+贪心)

    [题木链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1229 [题目大意] 每天对玩具都有一定的需求ni,每天可以花f价值每条购买玩具, 当天 ...

  5. 【树链剖分】bzoj2243 [SDOI2011]染色

    树链剖分模板题.线段树维护每个段中的颜色数.左端点颜色.右端点颜色. pushup: col[rt]=col[rt<<1]+col[rt<<1|1]-(Rcol[rt<& ...

  6. [JZOJ5426]摘Galo

    题目大意: 有一棵n个结点的树,每个点都有一个权值,你要从中选出不超过k+1个点使得权值和尽量大. 同时要注意如果一个点被选择,那么它的子树和这个点到根结点路径上的点不能被选择. 思路: 很水的树形D ...

  7. light oj 1236 - Pairs Forming LCM & uva 12546 - LCM Pair Sum

    第一题给定一个大数,分解质因数,每个质因子的个数为e1,e2,e3,……em, 则结果为((1+2*e1)*(1+2*e2)……(1+2*em)+1)/2. 代码如下: #include <st ...

  8. ES6的let和const命令

    刚开始学习es6,心里有点方,因为看了前言,感觉要用什么bebal来翻译成es5的代码,才能在各个平台上兼容运行,还有node各种运行环境. 不过自己也去百度了一些,发现还是有一丢丢的困难. 言归正传 ...

  9. iOS 日志管理异常捕获组件LFLogManager

    一.功能 1.分级打印保存 解决一大堆重要.不重要打印信息在控制台混为一团的尴尬局面.可设置仅打印某级别及以上的信息.分为5类打印: DDLogError(@"打印并保存特别重要信息&quo ...

  10. WiFi安全测试工具、蹭网利器–WiFiPhisher(转)

    读后感:看了一下官方介绍,需要2张无线网卡的支持,其中一张应该是用来影响用户和正常热点的连接,即进行dos攻击,而另外一张可以模拟一个假AP等待用户接入,这种攻击将对物联网和智能家居安防等产品造成很大 ...