- blogs:
- cles::blog
int arr[n]; はいつからできるようになったのか
c programmingC プログラミングを教えていときに「int arr[n]; のような感じで、配列の宣言時に変数が使えるのか?」と質問を受けたので、昔習ったとおり「できない」と答えたのですが、「実はこの書き方でもコンパイルが通ってしまうのですが・・・」と追い打ちをかけられたので、その理由を調べてみたら意外な結末を迎えてしまったのでその顛末をメモ。
C 言語も日々進化しているので、自分の知識も定期的にアップデートしなければならないことを実感しました。
† 今回のサンプルプログラム
単純な例だと以下のようなコードでしょうか。
var.c
† コンパイルしてみると・・・・
確かに gcc で何もオプションを付けないとコンパイルが通ってしまいます。
おそらく言語仕様の問題だという勘所は掴めたので std
と pedantic
を付けて順番に試してみます。
そうすると、c99
や c11
ではエラーが出ず、c90
だとエラーが出ることが分かりました。
エラーメッセージにvariable length array と書いてあるんで、これ variable length array と呼ばれている機能なんですね。
それはともかく、c99 と 20 年前の仕様から許されていたことにびっくり。
よく考えたら 20 年前は僕も大学生でしたので、そのときに習っていた C は c90 相当だったわけですね。
† 仕様書を調べて見る
というわけで、これは仕様に当たるしかないということで ISO の C 言語仕様を見比べてみることにします。
- [C90] ISO - ISO/IEC 9899:1990 - Programming languages — C
- [C99] ISO - ISO/IEC 9899:1999 - Programming languages — C
- [C11] ISO - ISO/IEC 9899:2011 - Information technology — Programming languages — C
とりあえず、仕様書で配列の宣言( Array declarators )の該当部分を調べていきます。
まず C90 を見てみると、明確に constant expression と書かれていて、[ ] 内は定数しか許されていないことが分かります。
[C90] §6.5.4.2 Array declarators
1 The expression delimited by [ and ] (which specifies the size of an array) shall be an integral constant expression that has a value greater than zero.
これに対して C99 の方は整数型 ( integer type ) とは書いてありますが、constant という表現は無くなっており、文法的にも [ ] 内に許される式が constant-expression から assignment-expression に変更されていることが確認できました。通常の整数の演算は assignment-expression に含まれているので、このことから配列の宣言に変数を使うことができることが分かります。また、第4項の後半にサイズが定数でない場合には variable length array (可変長配列)になるという記述が追加されていました。
[C99] §6.7.5.2 Array declarators
1 In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero.
4 (略) If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type;otherwise, the array type is a variable length array type.
さらに、C11 は C99 と同様の定義になっているのですが、先ほどの第4項がちょっと変更されていて、なぜか conditional feature になっています。
要はオプションなので、使えるかどうかはコンパイラ依存ということで、微妙に地雷のような感じがするのは僕だけでしょうか。
Visual Studio でこの機能が使えないのはこの辺りにヒミツがありそうです。
ちなみに §6.10.8.3 には _ _STDC_NO_VLA_ _ というマクロが定義されていて、これが 1 の時は VLA はサポートされてないということになるようです。
[C11] §6.7.6.2 Array declarators
4 (略) If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)
思った以上に根が深い問題でした。。。。。。
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/12021
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。
OpenID を使ってログインすることができます。
- シャープの空気清浄加湿器の... (1)
- SMARTEK デジタル温湿度計 (1)
2 . Word で数式がグレーアウトされていて挿入できないときは(15345)
3 . awk で指定した n カラム目以降を出力する(11828)
4 . アーロンチェアのポスチャーフィットを修理(11664)
5 . Windows 10 で勝手にログアウトされないようにする(9837)