C99は、ISO(
国際標準化機構)によって定められた
C言語の規格であり、正式な規格名は「ISO/IEC 9899:1999」です。この規格は、
C言語の標準化において重要な役割を果たしました。
歴史的背景
C99が制定される前、
C言語の仕様は
C++の進化に比べて停滞していました。1989年にANSIによって標準化されたC89(ISO/IEC 9899:1990)の後、
1995年には標準追補が作成されましたが、これはC89への細かい修正と国際文字集合への対応にとどまりました。
1990年代後半にいくつかの修正を経て、
1999年にISO/IEC 9899:1999として発行されたのがC99です。この規格は2000年5月にANSI標準としても受理され、国際的なC標準はISO/IEC JTC1/SC22/WG14という作業部会で保守されています。
新機能
C99では、多くの新機能が導入されました。その多くは、すでに様々な
コンパイラで拡張機能として実装されていたものです。
- - インライン関数: 関数呼び出しのオーバーヘッドを削減するための機能。
- - 変数宣言の制限緩和: ブロックの先頭以外でも変数宣言が可能になりました。
- - 新しいデータ型: `long long int`、拡張整数型、明示的なブーリアン型(`bool`)、複素数型などが追加されました。
- - 一行コメント: C++やBCPLのように`//`から始まる一行コメントが使用可能になりました。
- - 新しいライブラリ関数: `snprintf`などの新しいライブラリ関数が追加されました。
- - 新しいヘッダファイル: `stdbool.h`や`inttypes.h`などの新しいヘッダファイルが導入されました。
- - 型総称的な数学関数: `tgmath.h`による型に依存しない数学関数が利用可能になりました。
- - IEEE浮動小数点数: IEEE 754に準拠した浮動小数点数のサポートが強化されました。
- - 指示初期化子: 構造体の初期化をより柔軟に行えるようになりました(例:`struct foo f = {.x = 10, .y = 20};`)。
- - 可変引数マクロ: 可変個数の引数を受け取るマクロが利用可能になりました。
- - `restrict`修飾子: 最適化を促進するための修飾子が追加されました。
C89との後方互換性
C99は、ほとんどの場合C89と後方互換性がありますが、一部でより厳格な仕様となっています。特に、型が省略された宣言において、暗黙的に`int`と見なされることはなくなりました。C標準委員会は、不注意による型指定の欠落を診断することを重視しました。また、C89では宣言されていない関数は返り値の型が`int`で引数の数や型が任意の関数と解釈されていましたが、C99では文法違反となります。
C99の一部の機能は、
C++ Technical Report 1や
C++11に取り入れられています。これには、整数型、ヘッダファイル、ライブラリ関数などが含まれます。
- - GCC、Clang、Intel C++ Compiler: C99の多くの機能をサポートしています。ただし、GCCは完全に準拠しているわけではなく、一部にGNU拡張が含まれています。GCCのデフォルトは、以前はC89にGNU拡張を加えたものでしたが、現在ではC11にGNU拡張を加えたものがデフォルトとなっています。ClangのデフォルトはC99にGNU拡張を加えたものです。
- - Microsoft Visual C++: 2013年以降、C99の大部分を実装しています。当初は`tgmath.h`や`snprintf()`などが未実装でしたが、2017年以降は実装されています。
- - Open Watcom C compiler: 標準の中で最も使われている部分を実装しています。以前は、特定のコマンドラインスイッチが必要でしたが、現在は`za99`オプションで有効化できます。
- - Sun Studio: サン・マイクロシステムズは、C99を完全にサポートしていると表明しています。
- - Cインタプリタ Ch: C99の主要な機能をサポートしています。
ユーザー事例
GCCがC99の多くの機能に対応しているため、フリーソフトウェア開発などで広く利用されています。C99の複合リテラルや指示初期化子は、特に大規模なプロジェクトにおける保守性を向上させる上で大きな利点となります。Linuxカーネルでは、C99の指示初期化子を使う以前から、GCC拡張の指示初期化子を利用していました。以前はVisual StudioがC99に対応していなかったため、C99を使いたいプロジェクトでも利用できないことがありました。
QEMUでは指示初期化子を使用しつつC89との互換性を保つために`INIT_FIELD`マクロを導入しましたが、メンバーの省略ができないという欠点がありました。FFmpeg/libavでは、C99のソースコードをC89へ変換するトランスレータ`c99conv`や`c99wrap`を用意することで、この問題を解決しています。
バージョンの検知
標準マクロ`__STDC_VERSION__`は、C99をサポートしていることを示すために`199901L`と定義されています。C89の`__STDC__`マクロと同様に、`__STDC_VERSION__`はC89とC99の
コンパイラで異なるコードをコンパイルするために利用できます。たとえば、以下の例では、どちらの場合でも`inline`キーワードを利用可能にします。
c
if __STDC_VERSION__ >= 199901L
inline void foo(void) { /
... / }
else
void foo(void); /
inline is not available /
endif
後継規格
C99の後継規格は、C11(ISO/IEC 9899:2011)です。C99の受理後、標準作業部会は、組み込み分野、文字
データ型(
Unicodeのサポート)、境界チェック付きライブラリ関数などのためのテクニカルレポートを準備してきました。また、10進
浮動小数点数、数学の
特殊関数、動的メモリ確保関数の追加に関するテクニカルレポートについての作業も継続しています。Cと
C++の標準委員会は、スレッドに関する規格策定で協調して取り組んでいます。
2007年以降、非公式に「C1x」と呼ばれるさらなるC標準が期待されていましたが、標準委員会は、現在の実装でテストされていない新機能の採用を制限するというガイドラインを採用しました。また、安全でないインターフェース設計に関する不具合報告を受けて、`gets`関数が公式に廃止予定とされ、C11では削除されました。代わりに`gets_s`関数を使用する必要があります。
参照
- - ISO/IEC 9899:1999
- - C11 (ISO/IEC 9899:2011)