2017-05-09 9 views
1

code golfのコードを書いているうちに、私はいくつかの奇妙な動作に気がつきました。たとえば:なぜCコンパイラはこのエラーをキャッチしませんか?

int main(void) 
{ 
    goto jmp; 
    char *str = "Hello, World!"; 
jmp: 
    puts(str); 
} 

GCC(およびクランとMSVC)なし警告やエラーで結果をコンパイルし、実行しているが、それはSIGSEGVをスローします。どのようにコンパイラは、変数宣言の周りにgotoがジャンプしていることに気づかないのでしょうか?

が、私はこの(?バグ)アウトをテストすることを決めた、と例を書き直し:

再び
int main(void) 
{ 
    goto jmp; 
    int x; 
jmp: 
    putchar(x); 
} 

、コンパイルがエラーを生成しません。さらに、実行時に何もスローされませんが、MSVCではプロセスはゼロ以外の終了コードで終了します。

ここでは何が起こっていますか?これは単にgotoを使用しないでください。 2番目の例ではエラーは発生しませんが、最初にSIGSEGVがスローされます。

+0

これは未定義の動作です。変数宣言をスキップして、後でそれを使用しようとしました。これをやろうとしても、どうしたらいいのでしょうか?あなたはどんな結果を期待していますか? – InternetAussie

+2

これはコンパイラの仕事ではありません。 – kaylum

+2

@InternetAussie OPは彼がコードゴルフであると述べている。たぶん[this](https://codegolf.stackexchange.com/q/23250/61563)の挑戦ですか? –

答えて

4

ローカル変数の初期化を超えてジャンプすることが許可されていれば、その変数は初期化されていないことになります。

初期化されていない変数をputsに渡すと、undefined behaviourになりますが、制約違反や構文エラーはありません。これは、C標準ではコンパイラがエラーを出す必要がないことを意味します。

しかし、コンパイラは思慮深く、さまざまな警告フラグを提供する傾向があります。この場合、gccは初期化されていない変数の潜在的な使用について警告することができます。 -Wallまたは-Wuninitializedを使用すると、警告が表示されます。 -Werrorまたは-Werror=uninitializedを使用すると、警告ではなくエラーが発生します。

警告のある標準モードでは、常にコンパイルすることをおすすめします。 -std=c11 -pedantic -Wall -Wextra


"MSVCについては、プロセスはゼロ以外の終了コードで終了します。" MSVCコンパイラは、値を返さずにmainの末尾にあるC89標準までしかゴミを返しません。このような古代コンパイラをサポートする必要がある場合は、mainの末尾にreturn 0;が必要です。

関連する問題