C規格のバージョン

こんにちは、めのんです!

前々回に「次回はCのバージョンについて解説しようと思います」と予告していたのに1回割り込みが入ってしまいました。
気を取り直して、今回はCの標準規格のバージョンについて解説することにします。

PHPにもバージョンがあるようにCにもバージョンがあります。
といっても、PHPほど頻繁に仕様が変わることはありません。
おおまかに言って10年に1回ぐらいの改定です。

標準規格のバージョンとは別にコンパイラのバージョンアップもあるんですけど、こちらはそんなに気にする必要はないと思います。
コンパイラのバージョンがどの規格に準拠しているかだけを把握しておけばいいでしょう。

標準規格のバージョン

それでは、Cの標準規格の主なバージョンを見ていきましょう。
本当はこれら以外にも細かい正誤表があるんですけど、ここでは割愛させていただきます。

C90

Cの最初の標準規格ができたのは1989年のことでした(もう30年以上も前ですね)。
これはアメリカのANSIによるものでC89と呼ばれています。
国際標準規格としては翌年にISO/IEC 9899:1990が制定されています。

このバージョンは現在でも一番よく知られているバージョンだと思いますが、さすがに30年も前のものなので古いです。
当時の時代背景もあって制約も大きいように思います。

C95

この規格は先ほどのC90に対して主にライブラリの拡張を行ったもので、正式名称はISO/IEC 9899/AMD1:1995といいます。
その名の通り、制定されたのは1995年なのでC95の通称で呼ばれています。
拡張されたライブラリはワイド文字に関する内容がほとんどで、当時なりにI18Nを目指したようです。

実はこの規格に対応したコンパイラが一番普及したんだと思います。
プログラマーがC90までしか知らなかったとしても、破壊的変更がなかったので誰も気にしなかったんでしょうね。

C99

最初にANSIが標準規格を作ってから10年ぶりに大幅な仕様の改定が行われました。
正式名称はISO/IEC 9899:1999で、これがCの2nd Editionになります。
C95のようにライブラリも拡張されましたが、コア言語も大幅に拡張されました。
C95まではブロックの先頭でなければ変数などを宣言できなかったのが、ブロックの途中でも宣言できるようになるなど、ずいぶん利便性が向上しました。

このバージョンはJIS X3010:2003ということで日本のJIS規格にもなっています。
実はC95までも、それぞれに対応したJIS規格があるんですけど、今ウェブ上で閲覧できるのはこのJIS X3010:2003だけだと思います。
日本語で読める規格書ですので、ぜひ一度目を通してみてください。
https://www.jisc.go.jp/app/jis/general/GnrJISNumberNameSearchList?show&jisStdNo=X3010

この講座ではC99を中心に解説していこうと考えています。
とくに指定がない限り、C99についての話だと思っていただいてかまいません。
用語の日本語訳は、できるかぎりJIS X3010:2003に合わせるようにしますね。

C11

今世紀に入って最初の改定は2011年に行われました。
正式名称はISO/IEC 9899:2011で、これがCの3rd Editionになります。
このバージョンでようやくマルチスレッドが標準対応になります。

もう出てから10年近く経つんですけど、そんなに普及した感がありません。
この講座では余力があれば必要に応じて解説するようにしたいと思います。

C18

一応バージョンが振られているんですけど、実際にはC11に対するバグ修正だけです。
以前なら正誤表だけだったものが、フルセットの規格書になっただけのような気がします。
正式名称はISO/IEC 9899:2018です。

ところでこのバージョンは以前はC17と呼ばれていました(今でもC17と呼ばれることがあります)。
最終的にはISO/IEC 9899:2018というように2018年にできあがりましたので、C18と呼ぶのが正しいようです。
英語版のWikipediaでもそんな感じで書かれています。

GCCでのバージョン指定方法

Cの標準規格にはいくつかのバージョンがあることを見てきました。
私たちが使うコンパイラはGCCですので、GCCでのバージョン指定方法を理解しておく必要があります。

基本的なオプション

GCCで標準規格のバージョンを指定するには「-std」オプションを使います。
大雑把にいって、「-std=c99」のように書けばOKです(「c」は小文字で書きます)。
別名があるようなバージョン、たとえばC89とC90とかC17とC18のような場合はどちらを指定しても大丈夫です。
ただしC95だけは例外で、「-std=iso9899:199409」のように書く必要があります。

念のため、実際にコンパイルするときのコマンドを書いておきますね。

gcc -std=c99 -ohello hello.c

上のようになります。

GNU拡張を使う場合のオプション

先ほど解説した「-std=c99」のようなオプションは標準規格にできるだけ準拠させるためのオプションです。
GCCには標準規格にはない独自拡張機能がたくさん備わっています。
そうした独自拡張機能(GNU拡張やGCC拡張のように呼ばれています)を使うには「-std=gnu99」のように指定します。
「c」のところを「gnu」に変更するだけです(簡単ですね)。

最新のGCCはデフォルトが「-std=gnu17」になっています。
現時点でのGCCの最新バージョンは10.2ですが、gcc 5.xのころには「-std=gnu11」がデフォルトになっていました。
相当古いバージョンを引っ張り出さない限りはC11~C18が使えると思っていいでしょう。

先ほど、この講座ではC99を前提に解説すると書きましたが、デフォルトのままでもとくに支障はないと思いますのでコンパイルのコマンドを記載する場合は「-std=c99」を省略します。
あらかじめご了承ください。

厳密なことをいうと、C11からはgets関数が廃止されたり、可変長配列が任意実装になったりと破壊的変更があるんですけど、気にしないことにしましょう。

今回の解説は以上となります。
次回は変数と型について解説しようと思います。
また急に予定が変更になるかもしれませんが、そのときはご容赦ください。