120

次の簡略化されたコードがあります。

#include <stdio.h>
int main () 
{
    printf("Hello ");
    goto Cleanup;
Cleanup:
    char *str = "World\n";
    printf("%s\n", str);
}

ラベルの後に新しい変数が宣言されているため、エラーが発生します。{} ブロックのラベルの後にコンテンツ (主に初期化) を配置すると、コンパイルは成功します。

スイッチの場合のブロックの理由は理解できたと思いますが、ラベルの場合はなぜそれが適用されるのでしょうか?

このエラーは gcc コンパイラからのものです

4

2 に答える 2

167

言語標準は単にそれを許可していません。ラベルの後にはステートメントのみが続き、宣言は C のステートメントとしてカウントされません。これを回避する最も簡単な方法は、ラベルの後に空のステートメントを挿入することです。これにより、必要な方法でスコープを追跡する必要がなくなります。ブロックの中に。

#include <stdio.h>
int main () 
{
    printf("Hello ");
    goto Cleanup;
Cleanup: ; //This is an empty statement.
    char *str = "World\n";
    printf("%s\n", str);
}
于 2013-08-28T19:17:50.520 に答える
32

これは C 文法の癖です。ラベル( ) は宣言( など)のCleanup:直前には使用できず、ステートメント( )の前にのみ使用できます。C89 では、宣言はブロックの最初にしか現れないため、これは大きな問題ではありませんでした。そのため、常にラベルを少し下に移動して問題を回避することができました。C99 では、宣言とコードを混在させることができますが、宣言の直前にラベルを付けることはできません。char *str ...;printf(...);

ラベルのコロンの直後にセミコロンを配置して (Renan の提案に従って)、そこに空のステートメントを入れることができます。これは、機械生成コードで行うことです。または、宣言を関数の先頭に持ち上げます。

int main (void) 
{
    char *str;
    printf("Hello ");
    goto Cleanup;
Cleanup:
    str = "World\n";
    printf("%s\n", str);
    return 0;
}
于 2013-08-28T19:16:38.833 に答える