今日、私は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ステートメントの同じスコープ(私の場合はメイン関数のスコープ)内にあるため、ここではスコープは問題ではないと考えています。しかし、その後、なぜこのエラーが発生するのですか?
構文では単純に許可されていません。 §6.8.1ラベル付きステートメント:
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
「ラベル付き宣言」を許可する句はないことに注意してください。言語の一部ではありません。
もちろん、空のステートメントでこれを簡単に回避できます。
JUMP:;
int a = 0;
次のようなラベルの後にセミコロンが必要です。
#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を使用しています)。
簡単な説明は、仕様がそうではないことを除いて、コンパイラはgotoの後にコードを実行して、オフセットを計算できる操作にコンパイルするものであり、変数宣言がステートメントではないためキックしているということですそのようなオフセットにコンパイルできる/ block。
私のgccバージョン(4.4)でこのコンパイルエラーが発生しています:
t.c:7: error: a label can only be part of a statement and a declaration is not a statement
。このエラーメッセージはすべてを示しています。
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
}
まあ、最初に一貫性が必要です。 LABEL
またはlabel
です。第二に、ラベルはステートメントの一部であり、宣言は説明に十分に答えません。
LABEL:
をlabel: ;
に置き換えると、コンパイルする可能性が高くなります。
EDIT:コード全体を編集したので、JUMP:
をJUMP: ;
に置き換えてください;-)
それは、ラベル自体のせいではなく、すでにステートメント(gotoとprintf)があるからです。最新の標準では、任意の場所で変数宣言を許可しているようですが、すべてのコンパイラが標準に完全に準拠しているわけではありません。また、Cでは識別子の大文字と小文字が区別され、ラベルは両方の場所で同じでなければなりません。
#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);
}