回答:
と比較するC89
とC++
、ここにいくつかのものがあります
int n;
int n; // ill-formed: n already defined
int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]
int b(a) int a; { } // ill-formed: grammar error
struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)
auto a; // ill-formed: type-specifier missing
C99は他の多くのケースを追加します
// ill-formed: invalid syntax
void f(int p[static 100]) { }
// ill-formed: n is not a constant expression
int n = 1;
int an[n];
// ill-formed: fam has incomplete type
struct A { int a; int fam[]; };
// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);
typedef;
正当なTUですが、C ++ではありません。
auto a;
最新のC ++標準リビジョンで有効であることに注意してください。
a
何ですか?
auto x;
、最新のリビジョンでは無効ですが、たとえば有効ですauto x = 0;
。私は最初は少しショックを受けました:)
C ++にも新しいキーワードがあります。以下は有効なCコードですが、C ++ではコンパイルできません。
int class = 1;
int private = 2;
int public = 3;
int virtual = 4;
たくさんあります。単純な例(CがC ++の適切なサブセットではないことを証明するにはこれで十分です):
int* test = malloc(100 * sizeof(int));
Cではコンパイルできますが、C ++ではコンパイルできません。
int*
。
void *
。これは、Cでは任意のポインター型に割り当てることができ、C ++を他のポインター型に割り当てることはできません。
C ++では、、、またはを宣言するstruct
とunion
、enum
修飾子なしでその名前にすぐにアクセスできます。
struct foo { ... };
foo x; // declare variable
Cでは、このように宣言された型が独自の名前空間に存在するため、これは機能しません。したがって、次のように記述する必要があります。
struct foo { ... };
struct foo x; // declare variable
struct
2行目にそこに存在することに注意してください。union
and についてもenum
(それぞれのキーワードを使用して)同じことを行うか、typedef
トリックを使用する必要があります。
typedef struct { ... } foo;
foo x; // declare variable
その結果、曖昧さをなくすことができるため、Cで同じ名前の異なる種類の複数のタイプを持つことができます。
struct foo { ... };
typedef enum { ... } foo;
struct foo x;
foo y;
ただし、C ++では、struct
名前をstruct
参照するときにいつでもキーワードの前にキーワードを付けることができますが、名前空間はマージされるため、上記のCスニペットは無効です。一方、C ++は特に例外を作成して、型とその型のtypedefに同じ名前を付けることができるようにし(明らかに影響なし)、typedef
Cから変更されていないトリックを使用できるようにします。
struct
、union
とenum
)同じ名前空間を共有しています。より良い例は次のようになりますstruct foo { ... }; typedef enum { ... } foo;
これは、使用しているCの種類によっても異なります。Stroustrupは、C ++を1989 ANSIおよび1990 ISO規格と可能な限り互換性を持たせて互換性をなくし、1995バージョンは何も変更しませんでした。C委員会は1999年の標準とは多少異なる方向に進んでおり、C ++委員会は次のC ++標準を(おそらく来年くらいに)変更して、いくつかの変更に準拠させました。
Stroustrupは、「C ++プログラミング言語」の付録B.2に、C90 / C95との非互換性をリストしています。
'a'
はint
C内のchar
、C ++内のa です。
列挙型のサイズはint
Cであり、必ずしもC ++ではありません。
C ++には//
行末にコメントがありますが、Cにはありません(ただし、これは一般的な拡張機能です)。
C ++では、struct foo {
定義はfoo
グローバル名前空間に入れられますが、Cではそれをと呼ぶ必要がありstruct foo
ます。これにより、struct
定義が外部スコープで名前をシャドウイングできるようになり、他にもいくつかの影響があります。また、Cではstruct
定義のスコープを拡大でき、戻り値の型と引数の型の宣言でそれらを使用できます。
C ++は、一般的に型について面倒です。整数をに割り当てることはできずenum
、void *
オブジェクトはキャストなしで他のポインタ型に割り当てることはできません。Cでは、大きすぎる初期化子(char name[5] = "David"
Cは末尾のnull文字を破棄します)。
C89 int
は多くのコンテキストで暗黙的に許可されていましたが、C ++では許可されていません。これは、すべての関数はC ++で宣言する必要があることを意味しますが、C89ではint
、関数宣言に該当するすべてのものを想定することで問題を回避できることがよくありました。
Cでは、ラベル付きステートメントを使用してブロックの外側から内側にジャンプできます。C ++では、初期化をスキップする場合、これは許可されません。
Cは外部リンケージにおいてより寛大です。Cでは、グローバルconst
変数は暗黙的にextern
であり、C ++ではそうではありません。Cでは、グローバルデータオブジェクトを数回宣言することができます。extern
できますが、C ++ではそうではありません。
多くのC ++キーワードは、Cのキーワードではないか#define
、標準のCヘッダーではdです。
また、Cの古い機能のなかには、もはやスタイルとは見なされないものもあります。Cでは、引数のリストの後に引数定義を使用して関数を宣言できます。Cでは、のような宣言int foo()
は、foo()
任意の数の任意のタイプの引数を取ることができることを意味しますが、C ++では、と同等int foo(void)
です。
それはStroustrupからのすべてをカバーするようです。
私が考える1つの最大の違いは、これが有効なCソースファイルであることです。
int main()
{
foo();
}
foo
どこにも宣言していないことに注意してください。
言語の違いの他に、C ++はCから継承したライブラリにいくつかの変更を加えます。たとえば、一部の関数はのconst char *
代わりに戻りますchar *
。
s,C,C89,
して、それが無効なC99ソースファイルであることに注意してください。
#include <stdio.h>
int new (int n) {
return n/2;
}
int main(void) {
printf("%d\n", new(10));
return 0;
}
C ++ FAQエントリも参照してください。
ここでの回答の多くは、C89(またはC99)ソースコードでC ++コンパイラが失敗する原因となる構文の違いをカバーしています。ただし、両方の言語で合法である微妙な言語の違いはありますが、異なる動作を生成します。sizeof (char)
Naveenが言及したことに違いは一つの例ですが、(ANSI)Cプログラムとしてコンパイルされた場合、「C」を印刷するプログラム、および「C ++」C ++プログラムとしてコンパイルされた場合書き込みリストいくつか他の人を。
構文だけで言語を比較することはできません。そうすれば、CをC ++のサブセットとして見ることができるでしょう。私の意見では、C ++がOO(そしてCはそうではない)であるという事実は、CとC ++が異なる言語であると言うのに十分です。