12

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

现在我意识到用 C++ 编写有很多非常好的方法,但是我要在这里通过尝试使我的 C++ 版本尽可能像 FORTRAN 式来获得个人胜利。对于奖励积分,这可能会在我转换代码时为我节省一些时间和精力。

所以!这使我想到以下相关查询:

在 goto 上:

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


在 longjmp 上:

  1. 您将如何安全地使用 longjmp?
  2. C++ 中 longjmps 的限制是什么?
  3. 它对范围有什么作用?
  4. 是否有任何特定时刻看起来 longjmp 应该是安全的,但实际上我不应该提防?
  5. 如何使用 longjmp 模拟计算的 goto?
  6. 如果我的程序中只有一个函数,那么使用 longjmp 而不是 goto 有什么切实的好处吗?

现在我主要关心的是为此计算 goto 工作。看起来我可能会使用 longjmp 来完成这项工作,因为 void 指针数组不是 C++ 标准的一部分,而是 GCC 特定的扩展。

4

7 回答 7

7

我会咬一口并投反对票。

我严重怀疑你的朋友是否会发现用 C++ 编写的 Fortran 更容易阅读(如果你大量使用 goto 和 longjmp,这实际上是你会得到的),他甚至可能会发现它更难理解。C++ 语言与 Fortran 完全不同,我真的认为您不应该尝试从 Fortran 直接转换为 C++。它只会使 C++ 更难维护,您不妨保留现有的代码库。

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

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

于 2011-09-28T19:05:37.903 回答
4

你会得到很多关于使用的仇恨goto。通常我会直接赶上潮流,但在这种特殊情况下,这对我来说更像是代码高尔夫。所以给你。

用于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跳过变量的初始化,您可能会引发未定义的行为(将编译的代码,但您不能确定它实际上会做什么。)。
  • 您不能goto进入try块或catch处理程序。但是,您可以 goto try

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

于 2011-09-28T19:12:36.010 回答
3

我认为此参考资料包含您正在寻找的大部分信息。

长篇大论

于 2011-09-28T19:01:26.627 回答
3

计算goto-->switch

实际上,它们共享一个(常见但不通用的)底层实现作为跳转表。

于 2011-09-28T23:02:16.917 回答
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 goto 来实现 FORTRAN 计算的 goto!

于 2012-09-11T02:50:02.227 回答
0

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

于 2011-09-28T19:07:34.213 回答
0

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

于 2012-09-27T20:18:33.040 回答