2012-03-16 13 views
26

私はいくつかのCコードを書いています。私のコードには2つのネストループがあります。特定の条件では、内側のループからbreakに、外側のループではcontinueにしたいです。私は外側のループのコードの最後にラベルを使用してこれを達成しようとしましたが、その条件ではそのラベルgotoです。しかしgccは複合文の最後にラベルを付けることができないというエラーを出します。何故なの?Cでは、なぜgotoラベルの後に文が必要ですか?

注1:これはswitchの文ではなく、であり、の質問は、elsewhereと回答しています。

注2:これはスタイルについての質問ではなく、gotoステートメントまたは条件変数を使用する必要があるかどうかを問うものではありません。

EDIT:人々は、たとえばを求めていると、アレイはあなたが簡単に記述する必要が別の配列

int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...}; 
    int superIndex, subIndex; 

    for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1) 
    { 
     for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1) 
     if (superArray[superIndex+subIndex] != subArray[subIndex]) 
      goto break_then_continue; 

     // code that executes if subArray is a sub array 

     break_then_continue: 
    } 
+3

あなたが得るエラーメッセージを再現する小さなプログラムを提供することができますか? – sarnold

+0

Velociraptorsには幸運を覚えておいてください。 – wim

答えて

34

を明示的にあなたの後に簡単なセミコロン(;は)ので、ラベルが声明に属していることを言っていますラベルは、実行中の問題を回避することができます。これは、ステートメントとしてカウントされるためです。

6.8.3/6で "" のステートメントの使用にも例があります。これは呼ばれる複合ステートメント標準で

while (loop1) { 
    /* ... */ 

    while (loop2) { 
    /* ... */ 

    if (want_out) 
     goto end_loop1; 

    /* ... */ 
    } 

    /* ... */ 

    end_loop1: ; 
} 

のヌル文はまた、閉鎖直前に ラベルを運ぶために使用されてもよい

例3}からnull statementに変更してください。


6.8.1標示されたステートメントstatement上記の引用では任意ではないことを

Syntax 
    1 labeled-statement: 
     identifier : statement 
     case constant-expression : statement 
     default : statement 

注意。


+0

+1すばらしい答え。標準から直接取った例を大好き。 – Caleb

+0

偉大な応答をありがとう。私は*なぜ* gccがそれを回避する方法で動作するかを探していました。しかし、あなたの応答は、単にcが書かれている方法であることを示す傾向があります。これは主に、コンパイルがアセンブリコードをあまり抽象化していない時代の遺産である。 – AntonDelprado

+0

@AntonDelprado実際にはかなりシンプルですが、gotoはコマンド/式の前にラベルを置きます。そのようなものがなければ、ジャンプする場所はありません。空の文が使用されているので、これが可能です。 このようにNOP(無操作)アセンブリ関数の無害な同等物にジャンプします。 – AoeAoe

3

の部分配列である場合、私はチェックの少し容易な例を与えることができます:

label: ; 

セミコロンは空文です。言語はそのように定義されているため、必要となります。たとえそれが空のものであっても、あなたはステートメントに行く必要があります。

for (int i = 0; i < N; i++) 
    { 
     for (int j = 0; i < M; j++) 
     { 
      ... 
      if (some_condition) 
       goto continue_loop1; 
      ... 
     } 
continue_loop1: ; 
    } 

ラベルの字下げについて議論することができます。

+0

また、初期化を行っても、宣言はラベル付けできるステートメントではありません: 'label1:int x = function(y、z); 'は無効です。 –

3

ラベルはステートメントを指している必要があります。

Cの義務この:

「 どれ文がラベル名として識別子を宣言し、プレフィックスが先行することができる。」(C99は、6.8.1ラベル付きステートメントは、P4)

あなたのケースでは、ヌル文を使用することができます。

void foo(void) 
{ 
    goto bla; 

    bla: 
    ; 
} 

ヌル文は何も実行しません。

それとも、宣言を持っている場合、あなたはまた、複合文(ブロック)を使用することができます。標準で

void foo(void) 
{ 
    goto bla; 

    bla: 
    { 
     int x = 42; 
     printf("%d\n", x); 
    } 
} 
関連する問題