ホームに戻る
出典 :
関連 :
目次 :
C99 (ISO/IEC 9899:1999) とは
ISOで定められたC言語の規格。名称は1999年に発行されたことに由来している。
ANSIによる標準化(C89)以後、言語仕様の進化が遅れていたCに対して、C++の機能やコンパイラの独自機能を取り入れる大規模な改訂が行われた。
後継規格としてC11 (ISO/IEC 9899:2011) が存在する。
C99の新機能
ここに挙げるもの以外は出典元を参照。
インライン関数
関数の処理内容を呼び出し箇所に展開することで、通常の関数よりはるかに高速に実行することができる。
詳細はここを参照。
明示的なブーリアン型 (bool)
C++同様、ブーリアン値を格納するための bool 型および、真・偽を表す値 true 、false を使用可能。
使用するためには stdbool.h のインクルードが必要。
#include <stdbool.h>
bool b = false;
...
b = true;
倍精度長整数型のサポート (long long)
64ビットの幅を持つ (signed) long long (int) 、unsigned long long (int) を使用可能。
リテラルの接尾辞はそれぞれ LL 、ULL。
#define S8_MIN ( signed long long)0x8000000000000000LL //< signed long long int 最小値 (接尾辞LL)
#define S8_MAX ( signed long long)0x7FFFFFFFFFFFFFFFLL //< signed long long int 最大値 (接尾辞LL)
#define U8_MAX (unsigned long long)0xFFFFFFFFFFFFFFFFULL //< unsigned long long int 最大値 (接尾辞ULL)
ローカル変数の宣言位置制約の撤廃
C89ではローカル変数はコードブロック(関数など、{} (ブレース)で囲まれた区間)の先頭で宣言する必要があったが、
C99ではC++同様、コードブロックの途中でも変数を宣言できる 。
C89
int func(void)
{
/* 関数内で用いるローカル変数は
関数の先頭でまとめて宣言 */
int n;
int x;
DoSomething();
for (n=0; n<3; n++)
{
:
}
}
C99
int func(void)
{
int x;
DoSomething();
// ループ制御変数を、使用する直前に宣言
int n;
for (n=0; n<3; n++)
{
:
}
// ループ制御変数を for 節でのみ用いるのであれば、さらに短縮できる( for 文中で宣言・初期化)
for (int m=0; m<3; m++)
{
:
}
// for 節を抜けた時点で、m の寿命は終わっている
}
//から始まる一行コメント
BCPLやC++と同じスタイルでコメントを記述できる。従来の /* ~ */ スタイルも使用可能。
指示初期化子
配列・構造体の特定の要素を指定して初期化できる。
配列
// a[7] のみを初期化
int a[9] = {
[7] = 0
};
// 複数の要素を初期化(カンマで区切る)
int b[8] = {
[1] = 0, //< b[1]
1, //< 添字指定なし ⇒ ひとつ前の要素の次 ⇒ b[2]
[4] = 0, //< b[4]
2, //< b[5]
3, //< b[6]
};
// 不完全形(サイズ未知) ⇒ 指定された最大の添字からサイズが決定される ⇒ サイズ 6
int c[] = {
[4] = 0, //< c[4]
4, //< c[5] ⇒ 末尾
};
構造体
typedef struct tagSt_Rectangle
{
int x;
int y;
int width;
int height;
} St_Rectangle;
int main ()
{
St_Rectangle st_r =
{
.y = 0, //< 要素 y
100 //< 要素 y の次 ⇒ 要素 width
};
}
複合リテラル
構造体・配列(固定長のみ)をリテラルとして生成できる。
typedef struct tagSt_Point
{
int x;
int y;
} St_Point;
St_Point center(const St_Point*p1, const St_Point*p2)
{
// 戻り値を複合リテラルと指示初期化子を用いて生成
return (St_Point)
{
.x = (p1->x + p2->x) / 2,
.y = (p1->y + p2->y) / 2
};
}
int main(int argc, char **argv)
{
// center() の引数を複合リテラルを用いて生成
St_Point p = center(&(St_Point){1, 2}, &(St_Point){2, 3});
printf("(%d, %d)¥n", p.x, p.y);
}
上記の center() 関数は以下と等価である。
St_Point center(const St_Point*p1, const St_Point*p2)
{
// 戻り値を構成するための一時変数
St_Point ret =
{
(p1->x + p2->x) / 2,
(p1->y + p2->y) / 2
};
return ret;
}
即ち、暗黙の自動変数を生成している。(関数)スコープを抜けた時点でこの変数の寿命は終わってしまうため、以下のような記述は正常に動作しない。
St_Point* center(const St_Point*p1, const St_Point*p2)
{
// 暗黙の自動変数のアドレスを返す ⇒ 自動変数は関数を抜けると消滅するため参照できない
return &(St_Point)
{
.x = (p1->x + p2->x) / 2,
.y = (p1->y + p2->y) / 2
};
}
__func__ マクロ
現在実行中の関数名を取得できる。
void DoSomething()
{
// "DoSomethihg" が出力される
printf("%s", __func__);
}
その他、標準の定義済みマクロ一覧はリンク先を参照のこと。
注意すべき点( C89との相違 )
宣言時に型を省略した場合、C89では暗黙的に int と見なしていたが、C99ではコンパイルエラーとなる。
同様に、プロトタイプの無い関数はC89では戻り値の型は int 、引数の数、型は任意と解釈されるが、C99では文法違反となる。
即ち、プロトタイプ宣言(前方宣言)または前方定義が必須で、これらはいずれもC++と同様である。
コンパイラのバージョン判別
コンパイラがサポートしているCのバージョンは、標準マクロとして定義される __STDC_VERSION__ (標準Cバージョン)の値から判別できる。
__STDC_VERSION__ >= 199901L : C99(以降)
__STDC_VERSION__ >= 201112L : C11(以降)
尚、コンパイラがC++をサポートしているかはマクロ __cplusplus が定義されているかで確認できる。
GCCはC99の大半の機能をサポートするが、一部未実装のものもあり、完全準拠は果たしていない。
Microsoft Visual C++ は2013からC99の大半に適合する。
詳細はリンク先を参照のこと。