52409


独習Cの第三版で不明点があったので質問させていただきます。

以下引用ソースコードです。引用に問題などありましたらご指摘ください。

[code]

    #include <stdio.h>
    
    int main(void)
    {
        printf("このプログラムはコンパイルできません");
        int i; /* これを先に書くこと */
        i = 10;
        printf("%d", i);
    
        return 0;
    }
    
[/code]

出力と同じく本文中でも「以下の例は誤りですから、コンパイルエラーとなります。」とあったのですが、手元のgccとclangでコンパイルが通り実行も可能でした。

題目としてはローカル変数を扱う内容の部分で、ブロック内で変数宣言をする際はそのブロックの先頭にしなければならないとあり、私は「宣言よりもprintfがあるとダメなのか」と思いながら書き試してみたのですが動いてしまい、よくわからなくなりました。

これはどういったことなのでしょう…読みやすさを重視して変数宣言の前の出力はするべきでないといった意味なのか、それとも昔はダメでいつからか上記のようなものがエラーを起こさなくなったのか、またはwin版のコンパイラと何か違うのか…問題ないなら無視したいのですが気になってしまいました。

回答よろしくお願いします。


CC BY-SA 4.0
2019-01-30T01:58:23.173
52408
2019-01-30T02:49:36.347
31979
question
c
C言語の基礎（ローカル変数）


C言語の仕様が拡張されて、そうした記述を許すことになっています。  
書籍は、その前に書かれたか、以前の仕様を前提に書かれているのでしょう。

総体的に書かれた記事  
[C言語 - Wikipedia](https://ja.wikipedia.org/wiki/C%E8%A8%80%E8%AA%9E)

具体例を含む解説は、この記事などを参照してください。  
[連載：C言語の最新事情を知る（1）C99の仕様](https://www.buildinsider.net/language/clang/01)

> 変数宣言（C99／C11：§6.8.2）  
>  ANSI-Cまでは、関数内におけるローカル変数の宣言は、ブロック（※2015/10/19修正）の先頭で行う必要があった（リスト14）
[code]

    #include <stdio.h>
    #include <assert.h>
    
    int sum(int count, int a[]) {
      assert(count >= 0);
    
      int sum = 0; // ANSI-Cではエラー
      for (int i = 0; i < count; ++i) {  // ANSI-Cではエラー
        sum += a[i];
      }
      return sum;
    }
    
    int main(int argc, char **argv) {
      int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
      printf("sum = %d¥n", sum(sizeof(data) / sizeof(data[0]), data));
    }
    
[/code]

> リスト14は、ANSI-Cまでは文法エラーとなる。ANSI-
> Cまでは、変数の宣言はブロックの先頭に置く必要があったからだ。C99以降では文法が以下のように変更されている。
[code]

    compound-statement:
      { block-item-list(opt) }
    
    block-item-list:
      block-item
      block-item-list block-item
    
    block-item:
      declaration
      statement
    
[/code]

> 「compound-statement」がブロックを表す文法要素だが、「block-
> item」の定義を見ると分かるとおり、文と宣言とを任意の順序で記述できることが分かる。リスト14では、ブロックの途中に変数宣言が出現する他、for文の中で変数が宣言されている。これは仕様では§6.8.5（C99／C11）で規定されており、for文でのみ変数宣言を置くことが可能となっている（リスト16）。
[code]

    for ( declaration expression(opt) ; expression(opt) ) statement
    
[/code]

> ここで宣言された変数は、for文のブロック内でだけ有効となる（リスト17）。
[code]

    for (int i = 0; i < count; ++i) {
      sum += a[i];
    }
    printf("i = %d¥n", i); // エラー（変数未定義）
    
[/code]

連載の続き  
[C11の仕様－脆弱性対応に関連する機能強化点](https://www.buildinsider.net/language/clang/02)  
[C11の仕様－それ以外の主な機能強化点](https://www.buildinsider.net/language/clang/03)  
[C99でリソース管理ライブラリを作ってみる](https://www.buildinsider.net/language/clang/04)

関連記事  
[旧時代のC言語を使うのはそろそろやめよう。](https://qiita.com/raccy/items/8fd7765d1d22f29e5d82)  
[古いC言語(C89/C90)での変数宣言](https://qiita.com/yoyomion/items/892a375601bfaa065671)


CC BY-SA 4.0
2019-01-30T02:19:01.547
52409
2019-01-30T02:49:36.347
2019-01-30T02:49:36.347
26370
26370
52408
answer