ホームページ >バックエンド開発 >C#.Net チュートリアル >C++ ジャンプ ステートメント Goto が変数定義に及ぼす影響の詳細な説明

C++ ジャンプ ステートメント Goto が変数定義に及ぼす影響の詳細な説明

黄舟
黄舟オリジナル
2016-12-14 17:15:301728ブラウズ

はじめに

goto ステートメントは無条件転送ステートメントとも呼ばれ、その基本形式は次のとおりです:

ステートメントのラベルは有効な識別子と記号「;」で構成され、識別子の命名規則は同じです。つまり、文字、数字、アンダースコアで構成され、最初の文字は文字またはアンダースコアである必要があります。 goto ステートメントの実行後、プログラムはステートメントのラベルにジャンプし、後続のステートメントを実行します。

通常、goto文はif条件文と組み合わせて使用​​されますが、goto文はプログラムに柔軟性をもたらす一方で、プログラムの構造がわかりにくくなり、読みにくくなるため、合理的に使用する必要があります。

問題が見つかりました

Linux では goto の後に変数が定義され、コンパイルが失敗するという問題がよく発生します (エラー メッセージ: 初期化がクロスしています) の)。実は、今日、会社の先輩たちに聞いた後、いくつかの情報を調べて記録したので、誰かの参考になれば幸いです。

エラーサンプルコード:

#include <iostream>
using namespace std;
  
int main()
{
 goto Exit;
 int a = 0;
Exit:
 return 0;
}

エラーレポート:

[root@localhost c-c++]# g++ goto_study.cpp 
goto_study.cpp: In function &#39;int main()&#39;:
goto_study.cpp:31: error: jump to label &#39;Exit&#39;
goto_study.cpp:29: error: from here
goto_study.cpp:30: error: crosses initialization of &#39;int a&#39;

正しい書き方

は正しいとは言えず、コンパイルOKとしか言えません。

コードに直接移動:

書き方1:

ドメインを変更してローカル変数になる:

int main()
{
 goto Exit;
 {
 int a = 0;
 }
Exit:
 return 0;
}

書き方2

魔法の書き方:

int main()
{
 goto Exit;
 int a;
 a = 1;
Exit:
 cout << "a = " << a << endl;
 return 0;
}

鍵まだアクセスできるということです!結果:

[root@localhost c-c++]# g++ goto_study.cpp 
[root@localhost c-c++]# ./a.out
a = 1259648

研究

魔法の書き方

コンパイルして渡せる2つの書き方を見て、最も不可解なのは、2番目の書き方がコンパイルして渡せるのか、そしてそれが使えるのかということです。 ? ? ?

C++ の規制

参考文献 [1][2] では C++ 標準の規制について言及しています。 > ブロックに転送することは可能ですが、そうではありません。 初期化による宣言をバイパスする方法でジャンプするプログラム。 自動保存期間を持つローカル変数が存在しない時点から スコープ内のポイントへのスコープは、変数に POD がない限り不正な形式です type (3.9) であり、イニシャライザなしで宣言されています。

それは、プログラムの実行パスがコード内のポイント A (ローカル変数 x が定義されていない) からコード内の別のポイント B (ローカル変数 x が定義されていない) にジャンプする場合を意味します。変数 x が定義されており、定義時に初期化されている場合)、コンパイラはエラーを報告します。このようなジャンプは、goto ステートメントまたは switch-case を実行することによって発生する可能性があります。したがって、2 番目の書き方では、 a は int 型、POD 型であり、初期化されていないため、コンパイルは通ります。ただし、これは明らかです。先人が言ったように、この変数 a を使用した場合、結果は不明です。これは無意味です。サポートしない方がよいでしょう。ローカルでのみ使用する場合は、中括弧で囲むことができます。インターネット上の一部の人々は、C++ 仕様ではこれが間違っていると明示的には述べていないものの、変数ドメインの規定は実際にはこのアプローチは推奨されないことを暗黙的に示していると述べています。参考文献 [4] を参照してください。

暗黙の説明

Goto は変数の定義をスキップできません。 変数の有効期間はジャンプの時点から始まるため、ジャンプ後には存在しません。 定義には、goto を使用してはならないと明示的に記載されていないようです。

-fpermissive flag

参考文献[4]には、g++コンパイラがデフォルトでチェックすることが記載されていますが、コンパイラのこのフラグを警告ではなく警告に設定できます。実装されました! ! !

情報を確認しました - fpermissive マークの機能は、コードの構文エラーを警告として扱い、コンパイル プロセスを続行することです。安全のため、この観点からは考えないでください。コーディングにこだわりましょう!

POD 型

[3] を参照。上記の C++ 規則に従って、POD 型で初期化されていない限り、コンパイルして渡すことができます。 : コードの段落を見てください:

#include <iostream>
using namespace std;
class A{
public:
 // 注意:和B不同的是有构造和析构函数, 所以编译报错
 A(){}
 ~A(){}
 void testA(){
 cout << "A::test." << endl;
 }
};
class B{
public:
 void testB(){
 cout << "B::test." << endl;
 }
};
int main()
{
 goto Exit;
 // int a = 1; // windows ok.linux failed!
 //A classA; // failed:
 B classB; // success:
 classB.testB();
Exit:
 classB.testB();
 return 0;
}

結果:

[root@localhost c-c++]# g++ goto_study.cpp 
[root@localhost c-c++]# ./a.out
a = 1259648
B::test.
E

概要:

1. 上記のコードは Windows と Linux でコンパイルおよび実行されます。コンパイルは失敗します。 A にはコンストラクターとデストラクターがあるため、条件を満たしません。

3. int a = 1; に関しては、この書き方は Windows (msvc) で渡すことができますが、C++ の仕様と矛盾します。説明してください! ! !


以下は POD タイプです (英語で読んでみましょう):


1. int、char、wchar_t、bool、float、double は POD タイプであり、long/short、 署名付き/署名なしのバージョンにも同じことが当てはまります。 2. ポインター (関数ポインターとメンバー ポインターを含む) はすべて POD 型です。 3. enum 列挙型


4. POD の const 変数と通常の変数も同様です。 ;

5. POD型のクラス、構造体、共用体も同様です。ただし、すべてのメンバーはパブリックである必要があり、基本クラス、コンストラクター、デストラクター、仮想関数はありません。静的メンバーにもこれらのルールが適用されます。


まとめ


1. gotoを使用しないのが最善です;

2. goto 後の変数の定義と初期化をスキップしないでください。POD 型の場合は、最初に宣言してから定義することができ、コンパイル エラーは報告されません。ただし、この方法での使用は推奨されません。実行ステートメントが代入ステートメントをスキップすると、変数の値が不明で危険であることがわかります。

3. goto の後にローカル変数がある場合、その可能性があります。中括弧で囲んでローカル ドメインを形成することは安全です。

上記がこの記事の全内容です。この記事の内容が皆さんの学習や仕事に役立つことを願っています。ご質問がある場合は、メッセージを残して連絡してください。

その他の関連記事については、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。