【问题标题】:Is this a good way for unconditional jump?这是无条件跳转的好方法吗?
【发布时间】:2016-01-15 04:00:31
【问题描述】:

我在 func.c 文件中有一个函数 f(),在另一个文件 funcs.h 中有函数 f1()、f2()、f3()、f4()。 (假设所有函数都接收/返回值而不失一般性)。

  1. 函数 f( ) 调用 f4( )
  2. f4( ) 在它们之间以任意顺序调用 f1( )、f2( )、f3( )
  3. 在执行期间的某个时间点,f3() 检测到算法的完成,它必须“终止”算法的执行。在独立的情况下,它应该在打印解决方案后退出程序。但是在这里,我需要 f3( ) return 到 f()。

这是我的解决方案:

在这种情况下,我不能简单地返回 f4()(原来 f() 调用的函数,因为已经有 f1()、f2()、f3()、f4() 的函数调用堆栈,等待被“弹出”)。所以,我所做的是:

  1. 在调用 f4() 之前,我在 f() 中做了一个 setjmp( )
  2. 然后,当我检测到算法完成时,我在 f3( ) 中执行了longjmp( )

我的问题是:在这种情况下,这是实现这一目标的正确方法吗?

【问题讨论】:

  • 我已将其转换为 Wiki,因为这将涉及讨论,没有确定的答案。感谢您的所有意见。

标签: c


【解决方案1】:

TBH 我个人认为从函数返回布尔值更好,如果返回为真,则从下面的函数返回真,依此类推,直到它返回到原始函数。这会正确展开堆栈,我不确定 setjmp/longjmp 会这样做。

一般来说,如果你不打算在 f() 函数返回后继续做一些事情,它应该可以正常工作。我只是认为这不是一个很好的做事方式,因为阅读代码的人不会发现它像返回 bool 的函数那样明显。

【讨论】:

  • 返回bools 也是我的解决方案。如果要返回其他值,请将指针参数传递给应存储值的位置。
  • 感谢有关“bool”的提示。现在,它可以工作,但在其他情况下我可能会遇到“堆栈溢出”。我将尝试重新编码我的算法以利用它,看看它是否有帮助。
【解决方案2】:

您可以使用getcontext/setcontext。它们可以被视为 setjmp/longjmp 的高级版本;后者只允许单个非本地跳转堆栈,而 setcontext 允许创建多个协作控制线程,每个线程都有自己的堆栈。

也可参考其他相关调用如makecontext()、swapcontext()。
这是一个示例代码来展示如何使用这些函数(抱歉编码错误)。希望这对您有所帮助。

    #include <stdio.h>
    #include <ucontext.h>

    void func(void);

    int  x = 0;
    ucontext_t context, *cp = &context;

    int main(void) {

      getcontext(cp);
      if (!x) {
        printf("getcontext has been called\n");
        func();
      }
      else {
        printf("setcontext has been called\n");
      }

    }

    void func(void) {

      x++;
      setcontext(cp);

    }

  Output:

  getcontext has been called    
  setcontext has been called

【讨论】:

  • 感谢您的指点。即使在这里对我没有帮助,也很高兴知道。
  • 怎么样?与 setjmp/longjmp 相同。在 f() 调用 f4() 之前执行 getcontext,然后在 f3() 中,完成后只需执行 setcontext。它将返回到 f()。如果我没有理解您的要求,请纠正我。
  • @Vinit- 为什么我要在这里使用 setcontext/getcontext 而不是我的 setjmp/longjmp ?
  • getcontext/setcontext 可以看作是setjmp/longjmp的高级版;后者只允许单个非本地跳转堆栈,而 setcontext 允许创建多个协作控制线程,每个线程都有自己的堆栈。请参阅相同的手册页。
【解决方案3】:

f4( ) 在它们之间以任意顺序调用 f1( )、f2( )、f3( )

“任意顺序”是什么意思?除非您正在编写多线程程序,否则调用 1,2 和 3 的顺序应该是确定的;函数在 C 中同步执行。

【讨论】:

  • 我认为 f3() 可能有类似的东西: if ( someCondition ) { f3(something);否则 { f2(某事); }
  • 按任意顺序,我的意思是调用/返回的顺序在运行时是确定的。
【解决方案4】:

你没有提到你在做什么或你正在实现什么算法,但是......

您可以使用带有函数指针的全局结构,f1,f2,f3,f4 知道它的存在,然后从 f4() 调用 f1() 执行以下操作:

global.functionPointers[0]("parameters.for.f1");

【讨论】:

    【解决方案5】:

    难道你还需要一个标志来知道你不应该再次调用 f4 吗?

    int solution_found=0;
    
    f(){
      setjmp();
      if (!solution_found)
        f4();
      /* continue here... */
    }
    

    除此之外,setjmp/longjmp 可能是昂贵的调用。它们在程序的可读性方面也有代价。如果我是你,我当然会考虑让 f1,... 以正常方式将自己从堆栈中弹出。

    【讨论】:

    • 我肯定需要再次调用 f4(),但对于我的整体代码的下一次迭代。我想我需要在 funcs.h 的设计上投入更多的时间,看看是否能以正常方式弹出它们。
    【解决方案6】:

    我会这样做:

    struct solution { ... }
    
    solution *f() {
        solution *result;
        if (something) {
            result = f3();
            if (result != NULL)
                return result;
        }
        else {
            result = f3();
            if (result != NULL)
                return result;
        }
        return f();
    }
    

    或者无论你的算法是什么。

    【讨论】:

      猜你喜欢
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多