
C99 (開発中はC9X 、正式にはISO/IEC 9899:1999 ) は、 Cプログラミング言語のオープン標準の過去のバージョンです。[ 1 ]これは、言語と標準ライブラリの新しい機能で以前のバージョン ( C90 ) を拡張し、 IEEE 754-1985浮動小数点演算やコンパイラ技術などの利用可能なコンピュータ ハードウェアを実装がより良く利用できるように支援します。[ 2 ] 2011 年に公開された C プログラミング言語標準のC11バージョンは、C99 を更新したものです。
ANSIが1989年にC言語の公式規格を作成し、それが1990年に国際規格となった後、C言語の仕様はしばらくの間比較的静的なままでしたが、C ++は主に独自の標準化作業を通じて進化を続けました。1995年に規範的修正1によってCの新しい規格が作成されましたが、これは1989年の規格のいくつかの詳細を修正し、国際文字セットのサポートをより広範囲に追加することのみを目的としていました。この規格は1990年代後半にさらに改訂され、1999年にISO/IEC 9899:1999が発行され、2000年5月にANSI規格として採用されました。このバージョンの規格で定義されている言語は、一般に「C99」と呼ばれています。国際C規格は、ISO/IEC JTC1/SC22 /WG14ワーキンググループ によって維持されています。

C99は、大部分においてC89との下位互換性がありますが、いくつかの点でより厳格です。[ 3 ]
特に、型指定子のない宣言では、int暗黙的に が想定されなくなりました。C 標準化委員会は、暗黙的な に依存する従来のコードを黙って処理するよりも、型指定子の意図しない省略をコンパイラが診断する方が価値があると判断しましたint。実際には、コンパイラは警告を表示した後、 を想定してintプログラムの翻訳を続行する可能性が高いです。
C99ではいくつかの新機能が導入されましたが、その多くは既にいくつかのコンパイラで拡張機能として実装されていました。[ 4 ]
long long int、オプションの拡張整数型、明示的なブール型(_Bool)、および複素数を表す複素数型(型指定子)が含まれます。_Complex//snprintf<stdbool.h><complex.h><tgmath.h><inttypes.h><tgmath.h>を選択します。floatdoublelong doublestructXp={.i=1,.j=2};foo((structX){1,2})restrict資格により、より積極的なコード最適化が可能になり、以前はFORTRANがANSI C に対して持っていたコンパイル時の配列アクセスの利点がなくなります[ 7 ]\u0040または8桁の16進数シーケンス)を含めることができる。\U0001f431staticパラメータ宣言の配列インデックスのキーワード[ 8 ]:たとえば、が呼び出されるたびに、渡されたポインタは確実にnullではなく、少なくとも100個の要素を持つ配列を指していることをコンパイラに伝えます。[ 9 ] [ 10 ]voidfoo(intbar[static100]);foo()barintC99の一部の機能はC++から除外されました。特に可変長配列がそうです。C++は同様の目的で、次のようなシーケンシャルデータ構造を提供しています。std::vector<T>
C99 の主要な特徴は数値演算のサポートであり、特に、現代のプロセッサの大部分に搭載されているIEEE 754-1985 (IEC 60559 とも呼ばれる )浮動小数点ハードウェアの機能へのアクセスをサポートしている点です (「Annex F IEC 60559 浮動小数点演算」で定義されています)。IEEE 754 ハードウェアを搭載していないプラットフォームで も、ソフトウェアで実装できます。[ 2 ]
IEEE 754浮動小数点演算に対応したプラットフォームの場合:
floatはIEEE 754単精度、は倍精度、doubleはIEEE 754拡張精度(例: x86またはx86-64プラットフォーム上のIntel 80ビット倍精度拡張)、または利用可能な場合は何らかの形式の4倍精度として定義されます。それ以外の場合は倍精度です。long double FLT_EVAL_METHOD == 2、利用可能な場合 (たとえば80 ビットの double 拡張)、すべての内部中間計算がデフォルトで高精度 (long double) で実行されることを示しFLT_EVAL_METHOD == 1、 は、オペランドが long double でない限り、すべての内部中間式を double 精度で実行することFLT_EVAL_METHOD == 0を示し、 は、各演算子の最も広いオペランドの精度でのみ各演算が評価されることを指定します。特定の精度のオペランドの中間結果の型は、隣接する表にまとめられています。FLT_EVAL_METHOD == 2は、数値的に不安定な式に影響を与える丸め誤差のリスクを制限する傾向があり(IEEE 754 設計の根拠を参照)、 x87ハードウェアの設計上のデフォルト メソッドですが、不注意なユーザーにとっては直感的でない動作になります。[ 11 ]は、元々 K&R CFLT_EVAL_METHOD == 1で使用されていたデフォルトの評価方法で、式内のすべての float を double に昇格させました。また、一般的に使用されており、オペランドの厳密な「型への評価」を指定します。(gccの場合、は 32ビット x86のデフォルトであり、 は 64ビット x86-64のデフォルトですが、オプション -mfpmath=387 を使用して x86-64 で指定できます。)C99 より前は、コンパイラは、特にx87浮動小数点ハードウェアを使用している場合、中間結果を一貫性なく丸める可能性があり、コンパイラ固有の動作につながっていました。[ 12 ]このような不整合は、C99 に準拠するコンパイラでは許可されていません(付録 F)。 FLT_EVAL_METHOD == 0FLT_EVAL_METHOD == 2 FLT_EVAL_METHOD == 0 FLT_EVAL_METHOD == 2
以下に、連分数関数を計算するためのC99コードの注釈付き例を示します。
#include <assert.h>#include <fenv.h>#include <float.h>#include <math.h>#include <stdio.h>#include <stdbool.h>#include <tgmath.h>double compute_fn ( double z ) { // [1]#pragma STDC FENV_ACCESS ON // [2]assert ( FLT_EVAL_METHOD == 2 ); // [3]if ( isnan ( z )) { // [4]puts ( "zは数値ではありません" );}if ( isinf ( z )) {puts ( "zは無限大です" );}long double r = 7.0 - 3.0 / ( z - 2.0 - 1.0 / ( z - 7.0 + 10.0 / ( z - 2.0 - 2.0 / ( z - 3.0 )))); // [5, 6]feclearexcept ( FE_DIVBYZERO ); // [7]bool raised = fetestexcept ( FE_OVERFLOW ); // [8]if ( raised ) {puts ( "予期しないオーバーフローが発生しました。" );}return r ;}int main ( void ) {#ifndef __STDC_IEC_559__puts ( "警告: __STDC_IEC_559__ が定義されていません。IEEE 754 浮動小数点数は完全にはサポートされていません。" ); // [9]#endif#pragma STDC FENV_ACCESS ON#ifdef TEST_NUMERIC_STABILITY_UPfesetround ( FE_UPWARD ); // [10]#elif TEST_NUMERIC_STABILITY_DOWNfesetround ( FE_DOWNWARD );#endifprintf ( "%.7g \n " , compute_fn ( 3.0 ));printf ( "%.7g \n " , compute_fn ( NAN ));0を返す;}脚注:
gcc-std=c99-mfpmath=387-otest_c99_fptest_c99_fp.c-lmSTDCC標準で定義されています。)long doubleは、利用可能な場合は IEEE 754 倍精度拡張または 4 倍精度として定義されます。中間計算に必要な精度よりも高い精度を使用すると、丸め誤差を最小限に抑えることができます[ 13 ] ( typedef はdouble_t、すべての の下で移植可能なコードに使用できますFLT_EVAL_METHOD)。FLT_EVAL_METHOD2 と定義されている場合、定数を含むすべての内部計算は long double 精度で実行されます。 がFLT_EVAL_METHOD0 と定義されている場合は、これを確実にするために、追加のキャストや定数を long double として明示的に指定するなど、追加の注意が必要です。)__STDC_IEC_559__このマクロは、コンパイラとCライブラリによって「IEC 60559 浮動小数点演算に関する附属書F」が完全に実装されている場合にのみ定義されます(このマクロは、定義されるべきでない場合に定義されている場合があることにユーザーは注意する必要があります)。TEST_NUMERIC_STABILITY_UPこの例ではデバッグ時になどを定義することによって) することで、数値不安定性を診断できます。[ 14 ]この方法は、が別々にコンパイルされたバイナリ ライブラリの一部であっても使用できますcompute_fn()。ただし、関数によっては、数値不安定性を常に検出できるとは限りません。標準マクロは、 C99 サポートが利用可能であることを示す__STDC_VERSION__値で定義されます。C90用のマクロと同様に、このマクロを使用して、C90 コンパイラと C99 コンパイラで異なるコンパイルを行うコードを記述できます。この例では、どちらの場合でも が利用可能であることを確認しています (C90 では を に置き換えることでリンカ エラーを回避します)。199901L__STDC____STDC_VERSION__inlinestatic
#if __STDC_VERSION__ >= 199901L /* "inline" はキーワードです */ #else # define inline static #endifほとんどのCコンパイラは、C99で導入された機能の少なくとも一部をサポートしています。
歴史的に、マイクロソフトはVisual C++ツールに新しいC言語の機能を実装することに消極的で、主にC++標準の開発をサポートすることに重点を置いてきました。[ 15 ]しかし、Visual C++ 2013の導入により、マイクロソフトはC99の限定的なサブセットを実装し、Visual C++ 2015で拡張しました。[ 16 ]
1999年のC標準の承認以来、標準化ワーキンググループは、組み込み処理のサポート強化、追加の文字データ型(Unicodeサポート)、および境界チェック機能を強化したライブラリ関数に関する技術報告書を作成してきました。10進浮動小数点、追加の数学特殊関数、および追加の動的メモリ割り当て関数に関する技術報告書の作成作業は継続中です。CおよびC++標準化委員会は、スレッドプログラミングの仕様策定において協力しています。
C 標準の次の改訂版であるC11 は2011 年に承認されました。[ 44 ] C 標準委員会は、既存の実装でテストされていない新機能の採用を制限するガイドラインを採用しました。シーケンス ポイントを明確にし、スレッドプログラミングをサポートするために、メモリ モデルの開発に多大な労力が費やされました。