setjmp和longjmp函数

来源:互联网 发布:ubuntu软件卸载命令 编辑:程序博客网 时间:2024/05/21 11:31

今天发现一个特别有意思的函数对,setjmp和longjmp。

setjmp用于保存栈状态到指定buf中,longjmp用于把栈状态回复到指定buf存储的状态,同时返回到setjmp使用的地方。

setjmp第一次的返回值为0,调用longjmp后,执行位置从setjmp返回,返回值为longjmp指定的值。

这个函数对是C语言写的,存在于<setjmp.h>中。

函数声明格式为

extern int setjmp (jmp_buf __env) __THROWNL;

extern void longjmp (struct __jmp_buf_tag __env[1], int __val)
     __THROWNL __attribute__ ((__noreturn__));

其中

jmp_buf定义为

typedef struct __jmp_buf_tag jmp_buf[1];

 __jmp_buf_tag定义为

/* Calling environment, plus possibly a saved signal mask.  */
struct __jmp_buf_tag
  {
    /* NOTE: The machine-dependent definitions of `__sigsetjmp'
       assume that a `jmp_buf' begins with a `__jmp_buf' and that
       `__mask_was_saved' follows it.  Do not move these members
       or add others before it.  */
    __jmp_buf __jmpbuf; /* Calling environment.  */
    int __mask_was_saved; /* Saved the signal mask?  */
    __sigset_t __saved_mask; /* Saved signal mask.  */
  };


下面有个例子,是glibc中的使用范例。基本演示了怎么使用。

#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>


jmp_buf main_loop;


void
abort_to_main_loop (int status)
{
  longjmp (main_loop, status);
}

int
main (void)
{
  while (1)
    if (setjmp (main_loop))
      puts ("Back at main loop....");
    else
      do_command ();
}


void
do_command (void)
{
  char buffer[128];
  if (fgets (buffer, 128, stdin) == NULL)
    abort_to_main_loop (-1);
  else
    exit (EXIT_SUCCESS);
}

这个例子基本演示了两个函数是如何运行的。

只是 if (fgets (buffer, 128, stdin) == NULL)在我直接敲回车时还是收到了一个‘\n’,我是改为if (fgets (buffer, 128, stdin)[0] == '\n'),执行的。

还有一个例子,tst-setjmp.c中的例子,比较复杂,我理解是个死循环,估计是理解错了。明天再看看。



0 0
原创粉丝点击