web-dev-qa-db-ja.com

switchステートメント内の変数の宣言

この問題に対するいくつかの回答を見ましたが、それはわかりました。switch内で変数を宣言して割り当てることはできません。しかし、私は次のようなエラーを投げるのが正しいかどうか疑問に思っています

エラー: 'int'の前に式が必要です

コード:

_switch (i) {
    case 0:
        int j = 1;
        break;
}
_

なぜNSLog()を呼び出す前にエラーが発生しないのですか?

_switch (i) {
    case 0:
        NSLog(@"wtf");
        int j = 1;
        break;
}
_
113
dizy

実際にcan言語の構文に従って行う場合、スイッチ内で変数を宣言します。エラーが発生しているのは、「case 0: "はラベルであり、Cでは、ラベルの後の最初のステートメントとしてdeclarationを使用することは不正です—コンパイラはexpressionを予期することに注意してください、メソッド呼び出し、通常の割り当てなど(奇妙なことかもしれませんが、それがルールです。)

NSLog()を最初に置いたとき、この制限を回避しました。ケースの内容を{}中括弧で囲んでスコープブロックを導入するか、変数宣言をスイッチの外側に移動できます。どちらを選択するかは個人的な好みの問題です。 {}波括弧で宣言された変数はそのスコープ内でのみ有効であるため、それを使用する他のコードもそれらの波括弧内に表示する必要があることに注意してください。


編集:

ちなみに、この癖はあなたが思うほど珍しいことではありません。 CとJavaでは、forwhileで、ローカル変数宣言を単独のステートメントとして使用することも違法です(「中括弧で囲まれていない」ことを意味します) 、またはdoループ、またはifおよびelse条項(実際、これは "Java Puzzlers" のパズル#55でカバーされていますが、これを強くお勧めします)。 switch/caseコンストラクトでは、一部の人は省略しますbreakステートメントは制御フローの重要なステートメントであるため、中括弧。

コンパイラが適合をスローするのを確認するには、この恐ろしく無意味なスニペットを(Objective-)Cコードにコピーします。

if (1)
    int i;
else
    int i;
for (int answer = 1; answer <= 42; answer ++)
    int i;
while (1)
    int i;
do
    int i;
while (1);

このような構成体の本体を区切るために常に{}中括弧を使用するもう1つの理由。 :-)

139
Quinn Taylor

以前にこの問題に遭遇しましたが、結論はコードをブロック内に配置するだけでした。

switch (i) {
case 0:
    {
        int j = 1;
        break;
    }
}
46
newacct

私が使用する別の簡単な回避策は、宣言の前に空の式(セミコロン)を追加することです。これにより、変数スコープをコードブロックに限定する(または、コードブロックを使用するケースステートメントと使用しないケースステートメントを持つ)ことを回避できます。

switch (i) {
    case 0:;
        int j = 1;
        break;
}
3
Joel