2010-11-25 10 views
7

Cスイッチ/ケース内での変数の宣言

スイッチ/ケースブロック内でローカル変数を宣言する興味深い方法があります。代わりに、すべてのケースブロック内のブレースを使用しての、あなたが書くことができます。

switch (action) { 
    int res; 
    int value; 
case ACTION_OPEN: 
    res = open(...); 
    ... 
    break; 
case ... 
} 

をので、私はgccのサポートのほかにどのようなC/C++コンパイラ、この建設だろうか?それは一般的なフォールスルーのように見えます。この建設に関するコメントは大歓迎です!

+0

+1これが法的なC++かコンパイラの事故かどうかを調べるためだけです。許可されていると便利です。 –

+0

より簡単な方法は、11年以上前のCコンパイラの使用をやめることです。 –

+0

しかし、時折フォールスルーを除いて、私はまだより多くのローカルスコープのためにすべてのケースブロックの中括弧を好む。それは味の問題です。 – stefaanv

答えて

1

標準準拠のCコンパイラまたはC++コンパイラはこれを許可します。たとえ旧式の(C99より前の)Cコンパイラでもこれが可能ですが、変数宣言はブロック/複合ステートメント({}と表示されます)の先頭にあるためです。何switchを次のことcaseラベルの可能性を除いて、ほぼ正常の文であることを

注:

int main(int argc, char* argv[]) 
{ 
    switch (argc) 
     default: 
     puts("Hello, world!"); 

    return 0; 
} 

だから、ANSI C89で、それはここで魔法を行うブレースです。

3

スイッチ本体は普通のステートメント(あなたのケースでは、{ ... }のような複合ステートメント)ですが、これはどんなクラップも含むことができます。ケースラベルを含む。

このスイッチの考え方は、Duffs deviceによって悪用されています。

多くの人は、switch(0) ;のようなものであっても(複合文を使用する代わりに、本体としてnull文を使用する)有効な文であることに気づいていません。

+0

これは変数宣言とは関係ありません。 Duffは、彼の日のCコンパイラが余分なブロックを必要としていたので、彼の 'switch'ステートメントの中で変数を宣言しませんでした(おそらくプッシュ/ポップ命令に変換されたでしょう)。 –

+3

@larsmans Duffのデバイスは、変数の宣言とは関係ありませんが、CやC++で採用されているスイッチ構造を悪用することとすべて関連しています。特に、そのケースラベルは本当に「特別な」ものではなく、ジャンプラベルです。これがわかれば、スイッチ本体にケースラベルの前に宣言文を置くことは驚くことではありません。 –

-1

私は、ブロック内でどこでも変数を(ほぼ)宣言することができるので、動作は法的に考慮する必要があると思います。それは単なる宣言なので、実際のリスクはありません。

0

厳密に言えば、intと一緒にプレゼントするケースは、異なる理由で3つの言語すべてで許可されます。

Cは、すべてのケース(C89の場合)と1つの場合(C99の場合)のすべてのローカル変数(算術演算、structunion、配列...)の間でジャンプすることができます。 C99の例外は可変長配列です。

C++では、コンストラクタまたはデストラクタを持たないデータ型(PODとも呼ばれることがあります)に対してのみ、これが可能です。

あなたがC89で、あなたの例ではタイプT代わりのintを持っているのであれば、これは常に有効で、C99およびC++で、これは正しいか否かのタイプTに依存します。

いずれの場合でも、このすべてが初期化されていない変数につながりやすいため、避けることができない方が良いでしょう。