78

C99は 10 年以上前から存在していますが、サポートが遅れているため、ほとんどの開発者は C89 を使い続けています。今日でも、C コードで C99 の機能に出くわすと、少し驚くことがあります。

ほとんどの主要なコンパイラが C99 をサポートするようになったので (MSVC は顕著な例外であり、一部の組み込みコンパイラも遅れをとっています)、C を扱う開発者は、C99 のどの機能が利用できるかをおそらく知っておくべきだと思います。一部の機能は、これまで標準化されたことのない一般的な機能 (snprintfたとえば ) であるか、C++ でおなじみの機能 (柔軟な変数宣言の配置、または単一行//コメント) ですが、一部の新機能は C99 で最初に導入されたものであり、多くのプログラマーにはなじみがありません。

C99 の最も便利な新機能は何ですか?

参考までに、C99 標準(ドラフトとしてラベル付けされていますが、私が知る限り、更新された標準と同じです)、新機能のリスト、およびGCC C99 実装ステータス.

回答ごとに 1 つの機能をお願いします。複数の回答を残してください。新機能を示す短いコード例が推奨されます。

4

17 に答える 17

79

私はタイピングにとても慣れている

for (int i = 0; i < n; ++i) { ... }

C++ では、C99 以外のコンパイラを使用するのは面倒だと私は言わざるを得ません。

int i;
for (i = 0; i < n; ++i ) { ... }
于 2010-01-12T06:29:23.030 に答える
73

stdint.hint8_t、などを定義しuint8_tます。整数の幅について、移植性のない仮定を行う必要はもうありません。

uint32_t truth = 0xDECAFBAD;
于 2010-01-12T06:26:46.877 に答える
67

新しい初期化メカニズムは非常に重要だと思います。

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",
    ...
};
于 2010-01-12T06:50:40.523 に答える
52

で始まる 1 行コメントのサポート//

于 2010-01-12T06:19:09.933 に答える
51

可変長配列:

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]);
于 2010-01-12T14:28:51.763 に答える
41

ブロックの先頭以外の場所で変数を宣言できること。

于 2010-01-12T09:11:37.810 に答える
36

可変長マクロ。引数の数に制限がないボイラープレート コードの生成が容易になります。

于 2010-01-12T06:27:30.117 に答える
35

snprintf()- 真剣に、安全にフォーマットされた文字列を実行できることには多くの価値があります。

于 2010-01-12T17:53:37.180 に答える
29

柔軟な配列メンバー。

6.7.2.1 構造体および共用体指定子

特殊なケースとして、複数の名前付きメンバーを持つ構造体の最後の要素は、不完全な配列型を持つ場合があります。これは、柔軟な配列メンバーと呼ばれます。2 つの例外を除いて、柔軟な配列メンバーは無視されます。最初に、構造体のサイズは、柔軟な配列メンバーを未指定の長さの配列で置き換える他の点では同一の構造体の最後の要素のオフセットと等しくなければなりません.)->) 演算子には、柔軟な配列メンバーを持つ構造体 (へのポインター) である左オペランドがあり、右オペランドがそのメンバーの名前である場合、そのメンバーが (同じ要素型の) 最長の配列に置き換えられたかのように動作します。アクセスされるオブジェクトよりも構造体を大きくします。配列のオフセットは、置換配列のオフセットと異なる場合でも、柔軟な配列メンバーのオフセットのままです。この配列に要素がない場合、要素が 1 つあるかのように動作しますが、その要素にアクセスしようとしたり、その要素の 1 つ後ろにポインターを生成しようとした場合の動作は未定義です。

例:

typedef struct {
  int len;
  char buf[];
} buffer;

int bufsize = 100;
buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));
于 2010-01-12T17:55:31.137 に答える
29

複合リテラル。メンバーごとに構造を設定するのはとても'89です;)

それらを使用して、不要な変数を宣言せずに自動保存期間を持つオブジェクトへのポインターを取得することもできます。

foo(&(int){ 4 });

代わりに

int tmp = 4;
foo(&tmp);
于 2010-01-12T08:50:46.630 に答える
25

ブール型。

次のようなことができるようになりました。

bool v = 5;

printf("v=%u\n", v);

印刷します

1
于 2010-01-12T16:58:06.837 に答える
19

関数のサポートinline

于 2010-01-12T06:34:09.607 に答える
18

複合リテラル、すでに述べましたが、これが私の説得力のある例です:

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.  */

ヒープ上にある場合でも、データを初期化するための明確な方法です。何かをゼロ初期化することを忘れる方法はありません。

于 2011-11-04T09:21:43.810 に答える
17

restrictキーワード。特にあなたが数をクランチするとき...

于 2010-09-18T22:54:28.937 に答える
15

Unicode エスケープ シーケンスのサポート:

printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");

または、リテラル Unicode 文字でさえ:

printf("日本語\n");

(注: ロケールによっては機能しない場合があります。さまざまなエンコーディングの移植可能なサポートには、これよりも多くの作業が必要です)

于 2010-01-12T17:51:05.187 に答える
12

16 進浮動小数点定数 ( 0x1.8p0f) および変換指定子 ( %a, %A)。低レベルの数値の詳細を頻繁に扱う場合、これらは 10 進数のリテラルや変換よりも大幅に改善されます。

これらは、アルゴリズムの定数を指定する際の丸めに関する心配から解放され、低レベルの浮動小数点コードのデバッグに非常に役立ちます。

于 2010-01-12T19:39:56.970 に答える
9

個人的には、IEC 60559:1989 (マイクロプロセッサ システムのバイナリ浮動小数点演算) の承認と、はるかに優れた浮動小数点サポートが気に入っています。

同様に、浮動小数点の丸めモードの設定とクエリ、Nan/無限大/非正規数のチェックなどを行うと便利です。

于 2010-01-12T06:17:41.150 に答える