web-dev-qa-db-ja.com

gotoラベルの後の変数宣言

今日、私は1つの興味深いことがわかりました。 gotoラベルの後に変数を宣言できないことは知りませんでした。

次のコードをコンパイルする

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    int a = 0;  <=== giving me all sorts of error..
    printf("%d",a);
}

のようなエラーを与えます

temp.c: In function ‘main’:
temp.c:7: error: expected expression before ‘int’
temp.c:8: error: ‘a’ undeclared (first use in this function)
temp.c:8: error: (Each undeclared identifier is reported only once
temp.c:8: error: for each function it appears in.)

今、その背後にあるロジックは何ですか? switchのcaseステートメント内で変数を作成できないと聞いた。 JUMPはgotoステートメントの同じスコープ(私の場合はメイン関数のスコープ)内にあるため、ここではスコープは問題ではないと考えています。しかし、その後、なぜこのエラーが発生するのですか?

66
Krishnabhadra

構文では単純に許可されていません。 §6.8.1ラベル付きステートメント:

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

「ラベル付き宣言」を許可する句はないことに注意してください。言語の一部ではありません。

もちろん、空のステートメントでこれを簡単に回避できます。

JUMP:;
int a = 0;
84
Stephen Canon

次のようなラベルの後にセミコロンが必要です。

 #include <stdio.h>
 int main() {
     int x = 5;
     goto JUMP;
     printf("x is : %d\n",x);
 JUMP: ;     /// semicolon for empty statement
     int a = 0; 
     printf("%d",a);
 }    

その後、コードはgcc -Wall -std=c99 -c krishna.cを使用してC99標準用に正しくコンパイルされます(Debian/Sid/AMD64でGCC 4.6を使用しています)。

13

簡単な説明は、仕様がそうではないことを除いて、コンパイラはgotoの後にコードを実行して、オフセットを計算できる操作にコンパイルするものであり、変数宣言がステートメントではないためキックしているということですそのようなオフセットにコンパイルできる/ block。

6
jmoreno

私のgccバージョン(4.4)でこのコンパイルエラーが発生しています:

t.c:7: error: a label can only be part of a statement and a declaration is not a statement

。このエラーメッセージはすべてを示しています。

6
Patrick B.

Switchのcaseステートメント内で変数を作成できない理由がわかっている場合は、基本的にこれができない理由と同じです。修正として、これを試すことができます、

#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    {                                              //Note this
       int a = 0;  // <=== no more error..
       printf("%d",a);
    }                                             //Note this
}
2
COD3BOY

まあ、最初に一貫性が必要です。 LABELまたはlabelです。第二に、ラベルはステートメントの一部であり、宣言は説明に十分に答えません。

LABEL:label: ;に置き換えると、コンパイルする可能性が高くなります。

EDIT:コード全体を編集したので、JUMP:JUMP: ;に置き換えてください;-)

それは、ラベル自体のせいではなく、すでにステートメント(gotoとprintf)があるからです。最新の標準では、任意の場所で変数宣言を許可しているようですが、すべてのコンパイラが標準に完全に準拠しているわけではありません。また、Cでは識別子の大文字と小文字が区別され、ラベルは両方の場所で同じでなければなりません。

1
Alexey Frunze
#include <stdio.h>
int main() {
    int x = 5;
    goto JUMP;
    printf("x is : %d\n",x);
JUMP:
    printf("Do anything after label but dont declare 
    anything. even empty statement will also work 
    because label can only be part of a statement");
    int a = 0;  
    printf("%d",a);
}
0
Jeegar Patel