C99 は10年以上前から存在しますが、サポートが遅れているため、ほとんどの開発者はC89を使用しています。今日でも、CコードのC99機能に出くわしたときは、少し驚かされることがあります。
ほとんどの主要なコンパイラーがC99をサポートするようになった(MSVCは注目すべき例外であり、一部の組み込みコンパイラーも遅れている)ので、Cを扱う開発者は、C99のどの機能が利用できるかについて知っておくべきだと思います。一部の機能は、これまでに標準化されたことのない一般的な機能(snprintf
など)であるか、C++でよく知られています(柔軟な変数宣言の配置、または単一行//
コメント)、ただし、新機能の一部はC99で最初に導入され、多くのプログラマーには馴染みのないものです。
C99で最も便利な新機能は何ですか。
参考までに、 C99標準 (ドラフトとしてラベル付けされていますが、私の知る限り、更新された標準と同じです)、 新機能のリスト 、および- GCC C99実装ステータス 。
回答ごとに1つの機能をお願いします。複数の回答を自由に残してください。新しい機能を示す短いコード例をお勧めします。
私はタイピングに慣れています
for (int i = 0; i < n; ++i) { ... }
c ++では、C99以外のコンパイラを使用するのは面倒です。
int i;
for (i = 0; i < n; ++i ) { ... }
stdint.h
は、int8_t
、uint8_t
などを定義します。整数の幅について、移植性がないと仮定する必要はもうありません。
uint32_t truth = 0xDECAFBAD;
新しい初期化機構は非常に重要だと思います。
struct { int x, y; } a[10] = { [3] = { .y = 12, .x = 1 } };
OK-説得力のある例ではありませんが、表記は正確です。配列の特定の要素、および構造体の特定のメンバーを初期化できます。
多分もっと良い例はこれでしょう-私はそれがそれほど魅力的ではないことを認めますが:
enum { Iron = 26, Aluminium = 13, Beryllium = 4, ... };
const char *element_names[] =
{
[Iron] = "Iron",
[Aluminium] = "Aluminium",
[Beryllium] = "Beryllium",
...
};
可変長配列:
int x;
scanf("%d", &x);
int a[x];
for (int i = 0; i < x; ++i)
a[i] = i * i;
for (int i = 0; i < x; ++i)
printf("%d\n", a[i]);
//
で始まる1行コメントのサポート。
ブロックの先頭以外の場所で変数を宣言できること。
可変個のマクロ。引数の数に制限がないボイラープレートコードの生成が容易になります。
snprintf()
-真剣に、安全にフォーマットされた文字列を実行できることは多くの価値があります。
柔軟なアレイメンバー。
6.7.2.1構造体と共用体の指定子
特殊なケースとして、複数の名前付きメンバーを持つ構造体の最後の要素は、不完全な配列型になる場合があります。これはfl exible array memberと呼ばれます。 2つの例外を除いて、柔軟性のある配列メンバーは無視されます。最初に、構造体のサイズは、柔軟性のある配列メンバーを指定されていない長さの配列で置き換える、その他の点では同一の構造体の最後の要素のオフセットと等しくなければなりません)2番目、
.
(または->
)演算子には、可変配列メンバーと右オペランド名を持つ構造体(へのポインター)である左オペランドがありますそのメンバーは、そのメンバーが、アクセスされるオブジェクトよりも構造が大きくならない最も長い配列(同じ要素型を持つ)に置き換えられたかのように動作します。配列のオフセットは、これが置換配列のオフセットと異なる場合でも、フレキシブル配列メンバーのオフセットのままになります。この配列に要素がない場合は、1つの要素があるかのように動作しますが、その要素にアクセスしたり、1つ先のポインタを生成しようとしたりした場合の動作は未定義です。
例:
typedef struct {
int len;
char buf[];
} buffer;
int bufsize = 100;
buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));
複合リテラル。メンバーごとの構造の設定は'89;)です。
それらを使用して、不要な変数を宣言せずに、自動ストレージ期間を持つオブジェクトへのポインターを取得することもできます。
foo(&(int){ 4 });
の直感
int tmp = 4;
foo(&tmp);
ブール型。
あなたは今そのようなことをすることができます:
bool v = 5;
printf("v=%u\n", v);
印刷します
1
すでに述べた複合リテラルですが、ここに私の説得力のある例があります。
struct A *a = malloc(sizeof(*a));
*a = (struct A){0}; /* full zero-initialization */
/* or */
*a = (struct A){.bufsiz=1024, .fd=2}; /* rest are zero-initialized. */
ヒープ上にあってもデータを初期化する明確な方法です。何かをゼロ初期化することを忘れる方法はありません。
inline
関数のサポート。
restrict
キーワード。特にあなたが数を数えるとき...
Unicodeエスケープシーケンスのサポート:
printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");
または、リテラルUnicode文字:
printf("日本語\n");
(注:ロケールによっては機能しない場合があります。異なるエンコーディングのポータブルサポートは、これよりも多くの作業が必要です)
16進浮動小数点定数(0x1.8p0f
)および変換指定子(%a
、%A
)。低レベルの数値の詳細を頻繁に処理する場合、これらは10進リテラルと変換を大幅に改善します。
アルゴリズムの定数を指定する際の丸めの心配から解放され、低レベルの浮動小数点コードのデバッグに非常に役立ちます。
個人的に、私は IEC 60559:1989 (マイクロプロセッサシステムのバイナリ浮動小数点演算)の承認とはるかに優れた浮動小数点サポートを気に入っています。
同様に、浮動小数点丸めモードの設定とクエリ、Nan/Infinity /非正規数のチェックなどを行うのは素晴らしいことです。