CはC ++のサブセットではありませんか?[閉まっている]


116

CはC ++のサブセットであると多くの本を読みました。

一部の書籍では、細かい部分を除いて、 CはC ++のサブセットであるとしています

コードがCでコンパイルされ、C ++ではコンパイルされないケースは何ですか?

回答:


135

と比較するC89C++、ここにいくつかのものがあります

C ++では暫定的な定義はありません

int n;
int n; // ill-formed: n already defined

int []とint [N]は互換性がありません(C ++には互換性のある型はありません)

int a[1];
int (*ap)[] = &a; // ill-formed: a does not have type int[]

K&R関数定義スタイルがありません

int b(a) int a; { } // ill-formed: grammar error

ネストされた構造体はC ++でクラススコープを持っています

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);

@mehrdad、ありがとう。oOは、Cでネストされた構造体を宣言するときに、すでに変数を作成する必要があることを知りませんでした。修正されました。
Johannes Schaub-litb 2009

3
C89からC ++への別の(役に立たない)C1があります。Cではtypedef;正当なTUですが、C ++ではありません。
フレキソ

auto a;最新のC ++標準リビジョンで有効であることに注意してください。
fuz 2015

3
@FUZxxl本当に?推定されるタイプはa何ですか?
Johannes Schaub-litb 2015

3
@FUZxxlああありがとう。したがってauto x;、最新のリビジョンでは無効ですが、たとえば有効ですauto x = 0;。私は最初は少しショックを受けました:)
Johannes Schaub-litb '22 / 07/22

50

Cでは、sizeof('a')はに等しいsizeof(int)

C ++では、sizeof('a')はと同じsizeof(char)です。


46
これは、次のように簡略化できます。Cでは、'a'ですint。C ++では、'a'ですchar
pmg

38

C ++にも新しいキーワードがあります。以下は有効なCコードですが、C ++ではコンパイルできません。

int class = 1;
int private = 2;
int public = 3;
int virtual = 4;

1
それは本当ですが、それがまさにサブセットの意味です。
yeyeyerman 2009

20
@yeyeyerman:いいえ。サブセットにするためには、すべてのCコードも有効なC ++である必要があります。この例のコードは有効なCですが、C ++ではありません。
2009

24
いいえ、CがC ++の厳密なサブセットである場合、すべてのCプログラムは有効なC ++プログラムになりますが、そうではありません。問題はそれが真実ではない理由であり、これは理由の1つの例です。
Graeme Perrow、

ハ!これについては考えなかった!
Gab Royer、

20

たくさんあります。単純な例(CがC ++の適切なサブセットではないことを証明するにはこれで十分です):

int* test = malloc(100 * sizeof(int));

Cではコンパイルできますが、C ++ではコンパイルできません。


3
C ++では、への明示的なキャストが必要ですint*
Mehrdad Afshari、

8
長い答え:mallocはを返しますvoid *。これは、Cでは任意のポインター型に割り当てることができ、C ++を他のポインター型に割り当てることはできません。
Daniel Earwicker、2009

5
Imagist:ANSI C89標準で定義されているCコンパイラは文句を言うべきではありません。
Mehrdad Afshari、

7
これは正当なCです。キャストは不要であり、間違っている可能性があり、<stdlib.h>のインクルードの失敗を隠蔽します。私はMehrdadの文はCでそれを書くための正しい方法であることを考える
デヴィッド・ソーンリー

16
@Imagist:私は通常、Cプログラマーから反対のことを聞きます。バグを隠す可能性があるため、キャストを追加するのはスタイルが悪いと考えています。良いCコードはキャストを使用しませ
2009

16

C ++では、、、またはを宣言するstructunionenum修飾子なしでその名前にすぐにアクセスできます。

struct foo { ... };
foo x; // declare variable

Cでは、このように宣言された型が独自の名前空間に存在するため、これは機能しません。したがって、次のように記述する必要があります。

struct foo { ... };
struct foo x; // declare variable

struct2行目にそこに存在することに注意してください。unionand についても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に同じ名前を付けることができるようにし(明らかに影響なし)、typedefCから変更されていないトリックを使用できるようにします。


1
3個のタグ(:あなたの最後の例は無効Cであるstructunionenum)同じ名前空間を共有しています。より良い例は次のようになりますstruct foo { ... }; typedef enum { ... } foo;
schot

@schot:もちろんです。修正していただきありがとうございます。更新しました。
Pavel Minaev 2010

8

これは、使用しているCの種類によっても異なります。Stroustrupは、C ++を1989 ANSIおよび1990 ISO規格と可能な限り互換性を持たせて互換性をなくし、1995バージョンは何も変更しませんでした。C委員会は1999年の標準とは多少異なる方向に進んでおり、C ++委員会は次のC ++標準を(おそらく来年くらいに)変更して、いくつかの変更に準拠させました。

Stroustrupは、「C ++プログラミング言語」の付録B.2に、C90 / C95との非互換性をリストしています。

'a'intC内のchar、C ++内のa です。

列挙型のサイズはintCであり、必ずしもC ++ではありません。

C ++には//行末にコメントがありますが、Cにはありません(ただし、これは一般的な拡張機能です)。

C ++では、struct foo {定義はfooグローバル名前空間に入れられますが、Cではそれをと呼ぶ必要がありstruct fooます。これにより、struct定義が外部スコープで名前をシャドウイングできるようになり、他にもいくつかの影響があります。また、Cではstruct定義のスコープを拡大でき、戻り値の型と引数の型の宣言でそれらを使用できます。

C ++は、一般的に型について面倒です。整数をに割り当てることはできずenumvoid *オブジェクトはキャストなしで他のポインタ型に割り当てることはできません。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からのすべてをカバーするようです。


Cでは、スコープの先頭(つまり、左中括弧の直後)で変数を宣言する必要があるのに対し、C ++ではどこでも変数を宣言できることを忘れないでください。
RobH 2009

4
ただし、C ++ができることは、Cができないことです。私たちはC ++ではなくCでできることを検討していると思います。
David Thornley、

2
@RobH:これはC89には当てはまりますが、C99には当てはまりません。
jamesdlin

6

gccを使用している場合は、警告を使用できます -Wc++-compatを、C ++で何らかの疑わしいCコードに関する警告を表示できます。現在はgcc自体で使用されており、最近は大幅に改善されています(できる限りベストを得るには、毎晩のバージョンを試してみてください)。

(これは厳密に質問に答えるものではありませんが、人々はそれを好むかもしれません)。


1
無回答の回答には絶対に
賛成し

4

私が考える1つの最大の違いは、これが有効なCソースファイルであることです。

int main()
{
    foo();
}

fooどこにも宣言していないことに注意してください。

言語の違いの他に、C ++はCから継承したライブラリにいくつかの変更を加えます。たとえば、一部の関数はのconst char *代わりに戻りますchar *


確かに、プロトタイプはCでは必要ありませんが、通常は使用しないことをお勧めします。
ロバートギャンブル、

1
実行s,C,C89,して、それが無効なC99ソースファイルであることに注意してください。
Johannes Schaub-litb 2009

それは無効ですか、それともC99では非推奨ですか?
jalf

2
@jalf C99ドラフトはC89への変更を文書化し、「暗黙のintの削除」と「暗黙の関数の宣言の削除」の両方を含みます。
ヨハネスシャウブ-litb


2

ここでの回答の多くは、C89(またはC99)ソースコードでC ++コンパイラが失敗する原因となる構文の違いをカバーしています。ただし、両方の言語で合法である微妙な言語の違いはありますが、異なる動作を生成します。sizeof (char)Naveenが言及したことに違いは一つの例ですが、(ANSI)Cプログラムとしてコンパイルされた場合、「C」を印刷するプログラム、および「C ++」C ++プログラムとしてコンパイルされた場合書き込みリストいくつか他の人を。


-2

Cコンパイラは一般に、C ++ではできない小さなコーナーカットを許可していました。C ++はCよりもはるかに厳密です。そして一般的に、これらの違いのいくつかはコンパイラに依存しています。g ++は、たとえば、インテルC ++コンパイラーではできないいくつかのことを許可します。かなりよく書かれたCコードでさえ、最新のC ++コンパイラではコンパイルできません。


-2

構文だけで言語を比較することはできません。そうすれば、CをC ++のサブセットとして見ることができるでしょう。私の意見では、C ++がOO(そしてCはそうではない)であるという事実は、CとC ++が異なる言語であると言うのに十分です。


2
違う。C ++はオブジェクト指向だけではありません。「C ++ = C + OO +一般的なプログラミング+ボーナス」のようなC ++を考えることができます。言い換えると、「C&C ++〜= C」で、〜=はほぼ等しいことを意味します。
paercebal 2009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.