如何(计算)C ++中的goto和longjmp?

时间:2011-09-28 18:53:29

标签: c++ goto longjmp setjmp language-extension

我通常不会编写C ++代码,但我的一个奇怪的comp sci朋友厌倦了查看我精彩的FORTRAN程序并挑战我用C ++重写其中一个,因为他更喜欢我的C ++代码。 (我们在这里投入资金。)确切的条款是它需要在现代C ++编译器中进行编译。也许他讨厌一个好的conio.h - 我不知道。

现在我意识到在C ++中有很好的写作方式,但是我想通过尽可能使我的C ++版本成为FORTRAN-esque来获得个人胜利。对于奖励积分,当我转换代码时,这可能会节省一些时间和精力。

SO!这让我想到了以下相关问题:

关于getos:

  1. 你是如何工作的?
  2. C ++中对gotos的约束是什么?
  3. 对范围的担忧? (我将尽可能地尝试全局范围,但你永远不会知道。)
  4. 如果我使用GCC扩展转到void指针数组,是否有任何关于未定义行为的新问题等?

  5. 在longjmp上:

    1. 你如何安全地使用longjmp?
    2. C ++中对longjmps的约束是什么?
    3. 它对范围有什么影响?
    4. 是否有任何特定的时刻,看起来像一个longjmp应该是安全的,但实际上并不是我应该注意的?
    5. 如何使用longjmp模拟计算goto?
    6. 如果我的程序中只有一个函数,那么使用longjmp over goto会有什么明显的好处吗?
    7. 现在我主要担心的是为此计算goto。看起来我可能会使用longjmp来完成这项工作,因为void指针数组不属于C ++标准,但是GCC特定的扩展。

7 个答案:

答案 0 :(得分:7)

我会咬人并采取行动。

我非常怀疑你的朋友会发现使用C ++编写的Fortran更容易(如果你使用goto和longjmp,这将是你将得到的),他甚至可能会发现它更难以理解。 C ++语言与Fortran有很大不同,我认为你不应该尝试从Fortran到C ++的直接转换。它只会让C ++更难维护,你可以继续使用现有的代码库。

goto:您设置了一个标签(my_label:),然后使用goto命令goto my_label;,这将导致您的程序流在goto之后的语句中执行。您无法跳过变量的初始化或函数之间的跳转。您无法创建goto目标数组,但可以创建一个对象或函数指针数组以跳转到。

longjmp:如果您只有一个功能,则没有理由更喜欢longjmp而不是goto。但是,如果你只有一个函数,那么你真的不是在编写C ++,从长远来看,只要维护你的Fortran你会更好。

答案 1 :(得分:4)

你会得到很多关于使用goto的haterade。通常情况下,我会直接赶上潮流,但在这种特殊情况下,它听起来更像是高尔夫球。所以,你走了。

使用goto将指令指针移动到代码中的“标签”,这是一个C ++标识符,后跟一个冒号。这是一个工作程序的简单示例:

#include <iostream>
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    int i = 0;
step:
    cout << "i = " << i;
    ++i;
    if( i < 10 )
        goto step;

}

在这种情况下,step:是标签。

有关于背景的担忧。

  • 您只能goto到当前功能中的标签。
  • 如果你的goto跳过了变量的初始化,你可能会唤起Undefined Behavior(将编译的代码,但你不能确定它实际会做什么。)。
  • 您无法goto进入try块或catch处理程序。但是,可以 goto out try块。

如果满足其他问题,您可以使用指针等“转到”。如果有问题的指针在调用站点的范围内,并且在分支站点的范围内,则没问题。

答案 2 :(得分:3)

我认为此参考文献包含您要查找的大部分信息。

goto

longjmp

答案 3 :(得分:3)

计算goto - &gt; switch

实际上,他们共享一个(常见的,但不是通用的)基础实现作为跳转表。

答案 4 :(得分:1)

如果我理解原始问题,那么问题实际上是一个有趣的问题。重写问题(我认为是一个等价的问题):“你如何在C中进行FORTRAN计算goto?”

首先我们需要知道计算的goto是什么:这是一个解释的链接:http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm

计算GOTO的一个例子是:

    GO TO (12,24,36), INDEX

其中12,24和36是声明编号。 (C语言标签可以作为等价物,但不是唯一可以等同的东西。)

INDEX是一个变量,但可能是公式的结果。

这是在C中做同样事情的一种方式(但不是唯一的方法):

int SITU(int J, int K)
{
int raw_value = (J * 5) + K;

int index = (raw_value % 5) - 1;

return index;
}


int main(void)
{
int J = 5, K= 2;

// fortran computed goto statement: GO TO (320,330,340,350,360), SITU(J,K) + 1
switch (SITU(J,K) + 1)
{
case 0: // 320
    // code statement 320 goes here
    printf("Statement 320");
    break;
case 1: // 330
    // code statement 330 goes here
    printf("Statement 330");
    break;
case 2: // 340
    // code statement 340 goes here
    printf("Statement 340");
    break;
case 3: // 350
    // code statement 350 goes here
    printf("Statement 350");
    break;
case 4: // 360
    // code statement 360 goes here
    printf("Statement 360");
    break;
}

printf("\nPress Enter\n");
getchar();
return 0;
}

在这个特定的例子中,我们看到你不需要C gotos来实现FORTRAN计算的goto!

答案 5 :(得分:0)

Longjmp可以让你走出一个很好的信号处理程序 - 它会增加一些混乱,因为它不会在它跳转到setjmp行之前定义的函数中重置自动(基于堆栈)变量。 :)

答案 6 :(得分:0)

有一个名为 Labels as Values 的GCC扩展程序可以帮助您编写高尔夫代码,实际上是为您提供计算goto。当然,您可以自动生成标签。您可能需要这样做,因为您无法知道每行将生成多少字节的机器代码。