在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. 【最优比率生成树】poj2728 Desert King

    最优比率生成树教程见http://blog.csdn.net/sdj222555/article/details/7490797 个人觉得很明白易懂,但他写的代码略囧. 模板题,但是必须Prim,不能 ...

  2. 你真的完全了解Java动态代理吗?看这篇就够了

    之前讲了<零基础带你看Spring源码--IOC控制反转>,本来打算下一篇讲讲Srping的AOP的,但是其中会涉及到Java的动态代理,所以先单独一篇来了解下Java的动态代理到底是什么 ...

  3. Springcloud中的region和zone的使用

    一.背景 用户量比较大或者用户地理位置分布范围很广的项目,一般都会有多个机房.这个时候如果上线springCloud服务的话,我们希望一个机房内的服务优先调用同一个机房内的服务 ,当同一个机房的服务不 ...

  4. mysql 下 计算 两点 经纬度 之间的距离 含具体sql语句

    文章转载地址 http://blog.sina.com.cn/s/blog_7bbfd5fd01017d1e.html 感谢作者. 在原文的基础上,我新增了sql语句,方便大家理解 mysql距离计算 ...

  5. Manthan, Codefest 16 B. A Trivial Problem 二分 数学

    B. A Trivial Problem 题目连接: http://www.codeforces.com/contest/633/problem/B Description Mr. Santa ask ...

  6. Composer与laravel安装

    首先,要知道Composer是什么? Composer是PHP中用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer会帮你 ...

  7. JSON Bean 相互转换工具(效率是Gson的两倍以上)

    本帖最后由 xuehuayous 于 2015-12-24 08:44 编辑 前几天想封装一个自定义控件,用到Json解析,以前都使用Gson来解析Json数据的,但是想到一个简单的自定义控件就没必要 ...

  8. 利用谷歌API生成二维码

    http://chart.apis.google.com/chart?cht=qr&chs=104x104&chld=L|0&chl=http://www.cnblogs.co ...

  9. sso 自动化运维平台

    单点登录SSO(Single Sign-On)是身份管理中的一部分.本文中作者开发了一个自动化运维平台中的统一认证接口,单点登录平台通过提供统一的认证平台,实现单点登录.因此,应用系统并不需要开发用户 ...

  10. mongodb多表查询(附带pymongo实例)

    mongodb有$lookup可以做多表查询 举个例子 数据如下 db.orders.insert([ { , , }, { , , }, { } ]) db.inventory.insert([ { ...