12

私は通常C++をコーディングしませんが、私の奇妙な計算機科学の友人は、私のすばらしいFORTRANプログラムを見るのにうんざりし、私のC ++コードの方が好きなので、そのうちの1つをC++で書き直すように要求しました。(ここでお金を賭けています。)正確な用語は、最新のC++コンパイラーでコンパイル可能である必要があるということです。多分彼は良いconio.hを嫌っています-私は知りません。

今では、C ++で書くのに完全に良い方法があることに気づきましたが、C ++バージョンを可能な限りFORTRAN風にすることで、ここで個人的な勝利を収めようとしています。ボーナスポイントについては、コードを変換するときに時間と労力を節約できる可能性があります。

それで!これにより、次の関連クエリが表示されます。

gotosについて:

  1. どのように後藤を動かしますか?
  2. C ++でのgotoの制約は何ですか?
  3. スコープについて何か懸念はありますか?(私は可能な限りグローバルにスコープを設定しようとしますが、あなたは決して知りません。)
  4. GCC拡張機能を使用してvoidポインター配列に移動する場合、未定義の動作などに関する新しい懸念はありますか?


longjmpの場合:

  1. longjmpをどのように安全に使用しますか?
  2. C ++でのlongjmpsの制約は何ですか?
  3. スコープに対して何をしますか?
  4. longjmpが安全であるように見える特定の瞬間はありますが、実際には注意する必要はありませんか?
  5. longjmpを使用して計算されたgotoをどのようにシミュレートしますか?
  6. プログラムに関数が1つしかない場合、gotoよりもlongjmpを使用することに具体的なメリットはありますか?

今のところ、私の主な関心事は、このために計算されたgotoを機能させることです。voidポインタ配列はC++標準の一部ではなく、GCC固有の拡張機能であるため、おそらくlongjmpを使用してこれを機能させるようです。

4

7 に答える 7

7

私は噛んで反対票を投じます。

あなたの友人が C++ で書かれた Fortran を読むのがこれ以上簡単になるとは思えません (これは、goto と longjmp を大幅に使用すると効果的に得られるものです)。C++ 言語は Fortran とはかなり異なります。Fortran から C++ への直接的な変換を試みる必要はないと思います。C++ の保守が難しくなるだけで、既存のコードベースをそのまま使用することもできます。

goto: ラベル ( ) を設定してからmy_label:goto コマンドgoto my_label;を使用すると、goto に続くステートメントでプログラム フローが実行されます。変数の初期化や関数間を飛び越えることはできません。gotoターゲットの配列を作成することはできませんが、ジャンプ先のオブジェクトまたは関数ポインターの配列を作成できます。

longjmp:機能が 1 つしかない場合にlongjmp優先する理由はありません。gotoしかし、関数が 1 つしかない場合も、実際には 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に入ることができません。ただし、ブロックから出ることができます。trycatch goto try

You "can goto" with pointers etc provided the other concerns are met. If the pointer in question is in-scope at the call site and in-scope at the branch site, no problem.

于 2011-09-28T19:12:36.010 に答える
3

計算goto-->switch

実際、それらは (共通ではあるが普遍的ではない) 基になる実装をジャンプ テーブルとして共有しています。

于 2011-09-28T23:02:16.917 に答える
3

このリファレンスには、あなたが探しているほとんどの情報が含まれていると思います。

後藤

ロングジャンプ

于 2011-09-28T19:01:26.627 に答える
1

元の質問を理解していれば、その質問は実際には興味深いものです。質問を言い換えると(同等の質問だと思います):「CでFORTRANの計算されたgotoをどのように行いますか?」

最初に、計算された goto とは何かを知る必要があります。1 つの説明へのリンクを次に示します: 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 で同じことを行う 1 つの方法 (ただし、唯一の方法ではありません) を次に示します。

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;
}

この特定の例では、FORTRAN の計算された goto を実装するために C の goto は必要ないことがわかります。

于 2012-09-11T02:50:02.227 に答える
0

ゴルフをコーディングするのに役立つLabels as Valuesと呼ばれる GCC 拡張機能があり、基本的に計算された goto を提供します。もちろん、ラベルを自動的に生成することもできます。各行が生成するマシンコードのバイト数がわからないため、おそらくこれを行う必要があります。

于 2012-09-27T20:18:33.040 に答える
0

Longjmp を使用すると、シグナル ハンドラから抜け出すことができます。これは便利です。また、setjmp 行の前に定義されたロング ジャンプ先の関数内の自動 (スタック ベースの) 変数をリセットしないため、混乱が生じる可能性があります。:)

于 2011-09-28T19:07:34.213 に答える