C99 と C11 には非常に優れた機能がたくさんあるだけでなく、長年 (C90 以前) 存在していた多くの非互換性があります。これらはすべて私の頭のてっぺんから外れています。
// Valid C
int *array = malloc(sizeof(*array) * n);
// Valid C and valid C++, extra typing, it's always extra typing...
int *array = (int *) malloc(sizeof(*array) * n);
// Valid C++
int *array = new int[n];
C99 は素晴らしいので、世界中の C プログラマーが使用する必要があります
C99 の新機能は、一般的なプログラミングにとって非常に便利です。VLA および VLArestrict
は (私の意見では) 一般的な使用を対象としていませんが、主に FORTRAN および数値プログラマーを C に移行することを目的としています (ただしrestrict
、自動ベクトル化には役立ちます)。を使用する準拠プログラムは、ファイルの先頭にいるrestrict
場合でもまったく同じように動作するため (ただし、速度は遅くなる可能性があります) #define restrict
、大したことではありません。VLA は実際には非常にまれなようです。
柔軟な配列メンバーは便利です。 これらは可変長配列と同じではないことに注意してください! 人々はこのトリックを何年も使用してきましたが、公式サポートにより入力が少なくなり、コンパイル時に定数を作成できるようになりました。(古い方法ではサイズ 1 の配列を使用していましたが、割り当てサイズを計算するのは本当に面倒です。)
struct lenstr {
unsigned length;
char data[];
};
// compile time constant
const struct lenstr hello = { 12, "hello, world" };
指定された初期化子。 多くのタイピングを節約します。
struct my_struct { int a; char *b; int c; const char *d; };
struct my_struct x = {
.a = 15,
.d = "hello"
// implicitly sets b = NULL and c = 0
};
int hex_digits[256] = { ['0'] = 0, ['1'] = 1, ['2'] = 2, /* etc */ ['f'] = 15 };
inline
キーワードの動作は異なります。extern 宣言をそのユニットに追加することにより、インラインで宣言された関数の非インライン バージョンを取得する翻訳ユニットを選択できます。
複合リテラル。
struct point { float x; float y; };
struct point xy_from_polar(float r, float angle)
{
return (struct point) { cosf(angle) * r, sinf(angle) * r };
}
このsnprintf
関数は、おそらく C で最も有用なライブラリ関数のトップ 10 に入っています。C++ にないだけでなく、MSVC ランタイムは という関数しか提供して_snprintf
いません。これは、文字列に NUL ターミネータを追加することが保証されていません。(snprintf
これは C++11 にありますが、MSVC C ランタイムにはまだ明らかに存在しません。)
匿名の構造体と共用体(C11、しかし GCC の拡張機能は永遠に) (匿名の共用体は明らかに C++03 にあり、C モードでは MSVC をサポートしていません):
struct my_value {
int type;
union {
int as_int;
double as_double;
}; // no field name!
};
ご覧のとおり、これらの機能の多くは、入力の手間を省いたり (複合リテラル)、プログラムのデバッグを容易にしたり (柔軟な配列メンバー)、間違い (指定された初期化子/構造体フィールドの初期化の忘れ) を回避しやすくしたりします。これらは劇的な変化ではありません。
セマンティックの違いについては、エイリアシング ルールが異なると確信していますが、最近ではほとんどのコンパイラが十分に寛容になっているため、テスト ケースをどのように構築して実証するのかわかりません。誰もが到達する C と C++ の違いは古いsizeof('a')
式です。C++ では常に 1 ですが、32 ビット C システムでは通常 4 です。しかし、とにかく誰も気にしませsizeof('a')
ん。ただし、C99 標準には、既存のプラクティスを成文化する保証がいくつかあります。
次のコードを取ります。余分なストレージを無駄にすることなく、C でユニオン型を定義するための一般的なトリックを使用します。これは意味的に有効な C99 であり、意味的に疑わしい C++だと思いますが、間違っている可能性があります。
#define TAG_FUNKY_TOWN 5
struct object { int tag; };
struct funky_town { int tag; char *string; int i; };
void my_function(void)
{
struct object *p = other_function();
if (p->tag == TAG_FUNKY_TOWN) {
struct funky_town *ft = (struct funky_town *) p;
puts(ft->string);
}
}
しかし、それは残念です。 MSVC コード ジェネレーターは優れていますが、C99 フロントエンドがないのは残念です。