C言語での変数宣言ってどこに書けるのさ？

## Where have all the declarations gone?
某日某所、3人のプログラマの雑談より：
> Xさん「C言語って関数先頭でしか変数宣言できないから面倒だよねぇ。」
> Yさん「何いってんすか、`{`～`}`ブロックの先頭ならいつでも変数宣言できるしょ。」
> Zさん「いやいや、イマドキのC言語ならどこでも変数宣言できますから。」

さて3名のプログラマのうち、誰の主張が正しいのでしょう？もしかして、過去には彼らが言うような制限も実在したのでしょうか？[これってトリビアになりませんか？][trivial]

[trivial]: https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%AA%E3%83%93%E3%82%A2%E3%81%AE%E6%B3%89_%E3%80%9C%E7%B4%A0%E6%99%B4%E3%82%89%E3%81%97%E3%81%8D%E3%83%A0%E3%83%80%E7%9F%A5%E8%AD%98%E3%80%9C

このトリビアの種、つまりこういうことになります：
<b>「C言語で変数宣言を配置できる場所は ○○」</b>


## "C99"(1999年) ～ 現在まで
実際にプログラミング言語Cの言語仕様(Language Specification)を調べてみた。

2019年6月現在のC言語仕様は国際標準規格 [ISO/IEC 9899:2018][iso9899] として定義される。同規格はこれまでに 2011年、1999年 それぞれで改訂が行われており、ISO/IEC 9899:1999 における構文(Syntax)定義は次のようになっている。

> _compound-statement_:
> 　 　 `{` _block-item-list_<sub>opt</sub> `}`
> _block-item-list_:
> 　 　 _block-item_
> 　 　 _block-item-list_ _block-item_
> _block-item_:
> 　 　 _declaration_
> 　 　 _statement_

_compound-statement_(複合文) は`{`～`}`で囲われたブロックを表し、 _declaration_(宣言) が変数宣言に対応する。この構文定義からは、_compound-statement_(複合文) 中には **_declaration_(宣言) と _statement_(文) とを任意順序で記述可能** であると読み取れる。

> Zさん「いやいや、イマドキのC言語ならどこでも変数宣言できますから。」

つまり、Z氏の主張は 1999年以降のモダンなC言語 を指すと考えられる。

[iso9899]: https://www.iso.org/standard/74528.html


## "K&R C 1st Ed."(1978年) ～ "ANSI C"(1999年以前)

プログラミング言語Cは1989年に [ANSI C][ansic] として初めて標準化されたが、それ以前からC言語の生みの親 [ブライアン・カーニハン(Brian W. Kernighan)][kernighan] と [デニス・リッチー(Dennis M. Ritchie)][ritchie] 両名の名を冠した [書籍 "K&R C"][krbook] として言語仕様(相当)のリファレンスが存在していた。

書籍 "K&R C" は 第1版(1st Ed.) から 第2版(2nd Ed.) の間で大きく内容改訂されているが、ここでは1978年刊行の K&R C 第1版 より構文定義を引用する。

> _compound-statement_:
> 　 　 `{` _declaration-list_<sub>opt</sub> _statement-list_<sub>opt</sub> `}`
> _declaration-statement_:
> 　 　 _declaration_
> 　 　 _declaration_ _declaration-list_
> _statement-statement_:
> 　 　 _statement_
> 　 　 _statement_ _statement-list_

この構文定義からは、_compound-statement_(複合文) 中では **複数 _declaration_(宣言) に続く 複数 _statement_(文) の順序に限って記述可能** であると読み取れる。

> Yさん「何いってんすか、`{〜}`ブロックの先頭ならいつでも変数宣言できるしょ。」

つまり、Y氏の主張は 1978年以降かつ1999年より前のレガシーなC言語 を指すと考えられる。和暦でいうと 昭和53年以降かつ平成11年より前 である。

[ansic]: https://ja.wikipedia.org/wiki/ANSI_C
[krbook]: https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9EC
[kernighan]: https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%BB%E3%82%AB%E3%83%BC%E3%83%8B%E3%83%8F%E3%83%B3
[ritchie]: https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%8B%E3%82%B9%E3%83%BB%E3%83%AA%E3%83%83%E3%83%81%E3%83%BC


## "C Reference Manual"(1975年)

最後に、X氏の主張を検証してみよう。

> Xさん「C言語って関数先頭でしか変数宣言できないから面倒だよねぇ。」

書籍 "K&R 1st Ed." 時点でも 任意の _compound-statement_(複合文) 先頭において変数宣言が可能であったことから、X氏の言にあるC言語は実在しないのだろうか？

ここでX氏の名誉のために、プログラミングC言語の言語仕様に類する文書としては最古のものと考えられる、オペレーティングシステム [6th Edition Unix(UNIX v6)][unixv6] 付属のC言語コンパイラ・リファレンスマニュアル "[C Reference Manual][ancientc]" まで遡ってみる。

> _compound-statement_:
> 　 　 `{` _statement-list_ `}`
> _statement-list_:
> 　 　 _statement_
> 　 　 _statement_ _statement-list_

> _function-definition_:
> 　 　 _type-specifier_<sub>opt</sub> _function-declarator_ _function-body_
> _function-body_:
> 　 　 _type-decl-list_ _function-statement_
> function-statement:
> 　 　 `{` _declaration-list_<sub>opt</sub> _statement-list_ `}`

この構文定義からは、_compound-statement_(複合文) 中では 複数 _statement_(文) しか許容されず、**_function-body_(関数本体) でのみ 複数 _declaration_(宣言) に続く 複数 _statement_(文) の順序に限って記述可能** であると読み取れる。

> Xさん「C言語って関数先頭でしか変数宣言できないから面倒だよねぇ。」

つまり、X氏の主張は ["C言語"生誕(1972年)][history]から1975年頃の古代C言語 を指すと解釈するのが妥当であろう。X氏の名誉は守られたのだ。

[unixv6]: https://ja.wikipedia.org/wiki/Version_6_Unix
[ancientc]: https://qiita.com/yohhoy/items/6631443736ab779d3fbb
[history]: https://qiita.com/yohhoy/items/39cceda0cb62662fc76c


## まとめ
```
         │／
    ／￣＼●─
  ／～～⊂ニ⊃
／     ／￣＼
～～～／     ＼
こうしてこの世界にまた一つ
新たなトリビアが生まれた
```