1. ホーム
  2. c

[解決済み] C言語で新しい変数を宣言できる場所とできない場所とは?

2023-07-05 05:57:38

質問

プログラム/関数の先頭ですべての変数を宣言すべきであり、文の中で新しい変数を宣言すると問題が発生すると聞きました(おそらく先生から)。

しかし、K&R を読んでいて、次の文章に出会いました: "Declarations of variables (including initializations) may follow the left brace that introduces any compound statement, not just the one that starts a function". 彼はその後に例を挙げています。

if (n > 0){
    int i;
    for (i=0;i<n;i++)
    ...
}

このコンセプトで少し遊んでみたところ、配列でも動作することがわかりました。例えば

int main(){
    int x = 0 ;

    while (x<10){
        if (x>5){
            int y[x];
            y[0] = 10;
            printf("%d %d\n",y[0],y[4]);
        }
        x++;
    }
}

では、具体的にどのような場合に変数の宣言が許されないのでしょうか?例えば、変数宣言が開始波括弧の直後でない場合はどうでしょうか?ここのように。

int main(){
    int x = 10;

    x++;
    printf("%d\n",x);

    int z = 6;
    printf("%d\n",z);
}

プログラム/マシンによってはトラブルの原因になるのでは?

どのように解決するのですか?

また、変数を関数の先頭に置くのが一番良い方法だとよく聞きますが、私は強く反対です。私は、変数をできるだけ小さなスコープに閉じ込めることを好みます。そうすれば、誤用される可能性が少なくなり、プログラム上の各行で私の精神的空間を埋めるものが少なくなるからです。

C のすべてのバージョンでレキシカル ブロック スコープを許可していますが、変数を宣言できる場所は、ターゲットにしている C 標準のバージョンに依存します。

C99 以降または C++

gcc や clang のような最近の C コンパイラは C99 C11 という規格があり、文が通る場所であればどこでも変数を宣言することができます。変数のスコープは宣言の時点からブロックの終わり(次の閉じ中括弧)までとなります。

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line
   int z = 42;
   printf("%d", z);   // z is in scope in this line
}

ループの初期化子の内部で変数を宣言することもできます。変数はループの中だけに存在することになります。

for(int i=0; i<10; i++){
    printf("%d", i);
}

ANSI C (C90)

もしあなたが、古い ANSI C 規格を対象としている場合、変数の宣言は開始波括弧 1 .

しかし、これはすべての変数を関数の先頭で宣言しなければならないということではありません。C言語では、文が入る可能性のある場所ならどこでも中括弧で区切られたブロックを置くことができます(以下のようなものの後だけではありません)。 iffor ) を使って、新しい変数スコープを導入することができます。以下は、これまでのC99の例のANSI C版です。

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line

   {
       int z = 42;
       printf("%d", z);   // z is in scope in this line
   }
}

{int i; for(i=0; i<10; i++){
    printf("%d", i);
}}


1 gcc を使用している場合は --pedantic フラグを渡す必要があることに注意してください。もし、単に -std=c90 を使用すると、gcc は C90 のスーパーセットを受け入れるようになり、より柔軟な C99 変数宣言も可能になります。