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


Where have all the declarations gone?

某日某所、3人のプログラマの雑談より:


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

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

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


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

このトリビアの種、つまりこういうことになります:

「C言語で変数宣言を配置できる場所は ○○」


"C99"(1999年) ~ 現在まで

実際にプログラミング言語Cの言語仕様(Language Specification)を調べてみた。

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


compound-statement:

    { block-item-listopt }

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言語 を指すと考えられる。


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

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

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


compound-statement:

    { declaration-listopt statement-listopt }

declaration-statement:

    declaration

    declaration declaration-list

statement-statement:

    statement

    statement statement-list


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


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


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


"C Reference Manual"(1975年)

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


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


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

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


compound-statement:

    { statement-list }

statement-list:

    statement

    statement statement-list

function-definition:

    type-specifieropt function-declarator function-body

function-body:

    type-decl-list function-statement

function-statement:

    { declaration-listopt statement-list }


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


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


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


まとめ

     │/

  / ̄\●─
 /~~⊂ニ⊃
/   / ̄\
~~~/   \
こうしてこの世界にまた一つ
新たなトリビアが生まれた