C nerede bir C ++ alt kümesi değildir? [kapalı]


116

Birçok kitapta C'nin C ++ 'ın bir alt kümesi olduğunu okudum.

Bazı kitaplar , küçük ayrıntılar dışında C'nin bir C ++ alt kümesi olduğunu söyler .

Kodun C ile derleneceği, ancak C ++ 'da derlenmediği durumlar nelerdir?

Yanıtlar:


135

Eğer karşılaştırırsanız C89ile C++daha sonra burada birkaç şey vardır

C ++ 'da geçici tanım yok

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

int [] ve int [N] uyumlu değil (C ++ 'da uyumlu tür yok)

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

K&R işlevi tanımlama stili yok

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

İç içe geçmiş yapı, C ++ 'da sınıf kapsamına sahiptir

struct A { struct B { int a; } b; int c; };
struct B b; // ill-formed: b has incomplete type (*not* A::B)

Varsayılan int yok

auto a; // ill-formed: type-specifier missing

C99 pek çok başka durum ekler

Parametrelerin dizi boyutlarında bildirim belirticilerinin özel olarak işlenmesi gerekmez

// ill-formed: invalid syntax
void f(int p[static 100]) { }

Değişken uzunluklu diziler yok

// ill-formed: n is not a constant expression
int n = 1;
int an[n];

Esnek dizi üyesi yok

// ill-formed: fam has incomplete type
struct A { int a; int fam[]; }; 

Örtüşme analizine yardımcı olmak için kısıtlayıcı niteleyici yok

// ill-formed: two names for one parameter?
void copy(int *restrict src, int *restrict dst);

@mehrdad, teşekkürler. oO, C'de iç içe bir yapı bildirirken zaten bir değişken yaratması gerektiğini bilmiyordu. Düzeltildi.
Johannes Schaub - litb

3
Başka (işe yaramaz) C89'dan C ++ 'ya bir tane var: typedef;C'de yasal bir TU, ancak C ++' da değil.
Flexo

auto a;En yeni C ++ standart revizyonunda geçerli olduğuna dikkat edin .
Fuz

3
@FUZxxl gerçekten? Çıkarılan tür ne olacak a?
Johannes Schaub -

3
@FUZxxl ah teşekkürler. Yani auto x;en yeni revizyonda geçerli değildir, ancak örneğin geçerlidir auto x = 0;. İlk başta biraz şok oldum :)
Johannes Schaub - litb

50

C'de sizeof('a')eşittir sizeof(int).

C ++ ' sizeof('a')da eşittir sizeof(char).


46
Bu, şu şekilde basitleştirilebilir: C, 'a'bir int. C ++ ' 'a'da bir char.
pmg

38

C ++ da yeni anahtar kelimelere sahiptir. Aşağıdaki geçerli C kodudur, ancak C ++ altında derlenmez:

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

1
doğru, ama bu tam olarak alt küme demek.
yeyeyerman

20
@yeyeyerman: Hayır. Bir alt küme olması için, tüm C kodunun da geçerli C ++ olması gerekir. Bu örnekteki kod geçerli C'dir, ancak C ++ değildir.
jalf

24
Hayır, eğer C katı bir C ++ alt kümesi olsaydı, o zaman her C programı geçerli bir C ++ programı olurdu, ama bu doğru değil. Soru, neden doğru olmadığıdır ve bu, nedeninin bir örneğidir.
Graeme Perrow

Ha! Bunu düşünmedim!
Gab Royer

20

Bir çok şey var. Sadece basit bir örnek (C'nin uygun bir C ++ alt kümesi olmadığını kanıtlamak yeterli olacaktır):

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

C'de derlenmeli ancak C ++ 'da değil.


3
C ++ int*,.
Mehrdad Afshari

8
Uzun cevap: malloc void *, C'de herhangi bir işaretçi tipine atanabilen ve C ++ başka herhangi bir işaretçi tipine atanamaz.
Daniel Earwicker

5
Imagist: ANSI C89 standardında tanımlandığı gibi bir C derleyicisi şikayet etmemelidir.
Mehrdad Afshari

7
Yasal C'dir. Oyuncular gereksizdir, yanılmak mümkündür ve <stdlib.h> 'yi dahil etme başarısızlığını örtbas eder. Mehrdad'ın açıklamasını C
dilinde

16
@Imagist: Genelde C programcılarından tam tersini duyuyorum. Böcekleri gizleyebileceği için oyuncu kadrosu eklemenin kötü bir tarz olduğunu düşünüyorlar. İyi C kodu mu değil döküm kullanın.
jalf

16

Gümrüğe eğer C ++ ile bir struct, unionya da enum, adı herhangi elemeleri derhal erişilebilir:

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

C'de bu işe yaramaz, çünkü bu şekilde bildirilen türler kendi farklı ad alanlarında yaşarlar. Bu nedenle, yazmanız gerekir:

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

structİkinci satırdaki varlığına dikkat edin . Aynısını unionve için enum(ilgili anahtar kelimeleri kullanarak) yapmanız veya typedefhileyi kullanmanız gerekir :

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

Sonuç olarak, belirsizliği ortadan kaldırabileceğiniz için, C'de aynı adı verilen birkaç farklı türden olabilir:

struct foo { ... };
typedef enum { ... } foo;

struct foo x;
foo y;

Bununla birlikte, C ++ 'da, bir structadın structönüne anahtar kelime ekleyebildiğinizde , ad alanları birleştirilir ve bu nedenle yukarıdaki C pasajı geçerli değildir. Öte yandan, C ++, C'den typedefdeğişmeden hile kullanımına izin vermek için bir türün ve bu tür için bir typedef'in aynı ada (açıkçası etkisiz) sahip olmasına izin vermek için özel olarak bir istisna yapar .


1
Sizin son örneği geçersiz C: Üç etiketin ( struct, unionve enum) aynı ad paylaşır. Daha iyi bir örnek, struct foo { ... }; typedef enum { ... } foo;
06'da schot

@schot: Tabii ki haklısın, düzeltmen için teşekkürler. Güncellenmiş.
Pavel Minaev

8

Bu aynı zamanda ne tür C kullandığınıza da bağlıdır. Stroustrup, C ++ 'ı elinden geldiğince uyumlu hale getirdi ve artık 1989 ANSI ve 1990 ISO standartlarıyla uyumlu hale getirdi ve 1995 sürümü hiçbir şeyi değiştirmedi. C komitesi, 1999 standardıyla biraz farklı bir yöne gitti ve C ++ komitesi, bazı değişikliklere uymak için bir sonraki C ++ standardını (muhtemelen önümüzdeki yıl ya da öylesine) değiştirdi.

Stroustrup, C90 / C95 ile uyumsuzlukları "The C ++ Programming Language", Special Edition (bazı ek malzemelerle 3. basım) Ek B.2'de listeler:

'a'bir intC, bir charC ++ ' dır .

Bir numaralamanın boyutu intC'dir, C ++ 'da olması gerekmez.

C ++ //satırın sonuna kadar yorumlar içerir, C ise yoktur (yaygın bir uzantı olmasına rağmen).

C ++ 'da, bir struct foo {tanım fooglobal ad alanına yerleştirilirken, C' de buna struct foo. Bu, bir structtanımın dış kapsamdaki bir adı gölgelemesine izin verir ve başka birkaç sonucu vardır. Ayrıca C, structtanımlar için daha geniş kapsam sağlar ve dönüş türü ve bağımsız değişken türü bildirimlerinde bunlara izin verir.

C ++ genel olarak türler konusunda daha zahmetlidir. Bir tamsayının bir tamsayının atanmasına izin vermez enumve void *nesneler diğer işaretçi türlerine atanmadan atanamaz. C'de, aşırı büyük bir başlatıcı sağlamak mümkündür (char name[5] = "David" burada C, sondaki boş karakteri atacaktır).

C89 intbirçok bağlamda örtük olarak izin verirken C ++ izin vermez. Bu, tüm işlevlerin C ++ 'da bildirilmesi gerektiği anlamına gelirken, C89'da intişlev bildiriminde geçerli olan her şeyi varsaymak çoğu zaman mümkün olmuştur .

C'de, etiketli bir ifade kullanarak bir bloğun dışından içeriye atlamak mümkündür. C ++ 'da, bir başlatmayı atlarsa buna izin verilmez.

C dış bağlantıda daha liberaldir. C'de, küresel bir constdeğişken örtük externolarak bulunur ve bu C ++ 'da doğru değildir. C, global bir veri nesnesinin birextern , ancak bu C ++ 'da doğru değildir.

Çoğu C ++ anahtar sözcüğü, C'de anahtar sözcük değildir veya #definestandart C başlıklarında d'dir.

Ayrıca C'nin artık iyi bir stil olarak görülmeyen bazı eski özellikleri de var. C'de, bağımsız değişkenler listesinden sonra bağımsız değişken tanımlarına sahip bir işlev bildirebilirsiniz. C'de, benzeri bir bildirim, herhangi bir sayıda argüman alabilen int foo()anlamına foo()gelirken, C ++ 'da buna eşdeğerdir int foo(void).

Bu Stroustrup'tan gelen her şeyi kapsıyor gibi görünüyor.


Unutmayalım ki, C'de değişkenleri bir kapsamın başında (yani, bir açılış ayracından hemen sonra) bildirmeniz gerekir, oysa C ++ her yerde değişken bildirimlerine izin verir.
RobH

4
Ancak, bu C ++ 'nın yapabileceği, C'nin yapamadığı bir şeydir. Sanırım C ile yapabileceğiniz şeylere bakıyoruz ama C ++ 'da değil.
David Thornley

2
@RobH: Bu C89 için doğru ama C99 için değil.
jamesdlin

6

Gcc kullanıyorsanız, uyarıyı kullanabilirsiniz -Wc++-compat C ++ 'da bir şekilde şüpheli olan C kodu hakkında uyarılar vermek için . Şu anda gcc'nin kendisinde kullanılıyor ve son zamanlarda çok daha iyi hale geldi (elinizden gelenin en iyisini elde etmek için gecelik bir sürümü deneyebilirsiniz).

(Bu soruya kesin olarak cevap vermez, ancak halk hoşuna gidebilir).


1
Cevapsız yanıtı asla yükseltmeyeceğimi düşünmüştüm
eharo2

4

Bence en büyük tek fark, bunun geçerli bir C kaynak dosyası olmasıdır:

int main()
{
    foo();
}

Beyan etmediğimi unutmayın foo yerde .

Dil farklılıklarının yanı sıra, C ++, C'den miras aldığı kitaplıkta bazı değişiklikler de yapar, örneğin bazı işlevler const char *yerine geri döner char *.


Doğru, C'de prototipler gerekli değildir, ancak bunları kullanmamak genellikle kötü bir uygulama olarak kabul edilir.
Robert Gamble

1
Yapmalı s,C,C89,ve bunun geçersiz bir C99 kaynak dosyası olduğuna dikkat etmelisiniz .
Johannes Schaub - litb

Geçersiz mi yoksa sadece C99'da kullanımdan kaldırıldı mı?
jalf

2
@jalf C99 taslağı, C89'daki değişiklikleri belgeler ve hem "örtük int'i kaldır" hem de "örtük işlev bildirimini kaldır" içerir.
Johannes Schaub - litb


2

Buradaki yanıtların bir kısmı, C ++ derleyicilerinin C89 (veya C99) kaynak kodunda başarısız olmasına neden olacak sözdizimi farklılıklarını kapsar. Bununla birlikte, her iki dilde de yasal olan ancak farklı davranışlar üretecek bazı ince dil farklılıkları vardır. sizeof (char)Naveen bahsettiği fark bir örnektir, ama bir bir (ANSI) C programı olarak derlenmiş eğer "C" yazdırır programı ve "C ++" C ++ programı olarak derlenmiş eğer yaz listeleri bazıları.


-2

C derleyicileri genellikle C ++ 'nın izin vermediği küçük bir köşe kesmeye izin verir. C ++, C'den çok daha katıdır. Ve genel olarak, bu farklılıklardan bazıları derleyiciye bağlıdır. g ++, örneğin Intel C ++ derleyicisinin izin vermediği bazı şeylere izin verir. Oldukça iyi yazılmış C kodu bile modern bir C ++ derleyicisiyle derlenmez.


-2

Dilleri yalnızca sözdizimine göre karşılaştıramazsınız. Bunu yaparsanız, belki C'yi C ++ 'nın bir alt kümesi olarak görebilirsiniz. Bana göre C ++ 'nın OO olduğu (ve C'nin olmadığı) gerçeği C ve C ++' nın farklı diller olduğunu söylemek için yeterli.


2
Yanlış. C ++ yalnızca OO değildir . C ++ 'yı "C ++ = C + OO + genel programlama + bonuslar" gibi düşünebilirsiniz. Başka bir deyişle, "C & C ++ ~ = C" burada ~ = neredeyse eşit anlamına gelir.
paercebal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.