Dimana C bukan bagian dari C ++? [Tutup]


116

Saya membaca di banyak buku bahwa C adalah bagian dari C ++.

Beberapa buku mengatakan bahwa C adalah bagian dari C ++, kecuali untuk detail kecilnya .

Apa sajakah kasus ketika kode akan dikompilasi dalam C, tetapi bukan C ++?

Jawaban:


135

Jika Anda membandingkan C89dengan C++maka di sini adalah beberapa hal

Tidak ada definisi tentatif di C ++

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

int [] dan int [N] tidak kompatibel (tidak ada tipe yang kompatibel di C ++)

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

Tidak ada gaya definisi fungsi K&R

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

Struct bersarang memiliki cakupan kelas di C ++

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

Tidak ada int default

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

C99 menambahkan banyak kasus lainnya

Tidak ada penanganan khusus penentu deklarasi dalam dimensi array parameter

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

Tidak ada array dengan panjang variabel

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

Tidak ada anggota array yang fleksibel

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

Tidak ada batasan kualifikasi untuk membantu analisis aliasing

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

@mehrdad, terima kasih. oO tidak tahu bahwa seseorang harus membuat variabel saat mendeklarasikan struct bersarang di C. Tetap.
Johannes Schaub - litb

3
Ada C89 lain (tidak berguna) ke C ++ satu: typedef;adalah TU legal di C, tapi tidak di C ++.
Flexo

Perhatikan bahwa auto a;ini valid dalam revisi standar C ++ terbaru.
fuz

3
@FUZxxl benarkah? Apa yang akan menjadi jenis deduksi a?
Johannes Schaub - litb

3
@FUxxl ah terima kasih. Jadi auto x;tidak valid di revisi terbaru, tapi contohnya auto x = 0;adalah. Awalnya saya agak kaget :)
Johannes Schaub - litb

50

Di C, sizeof('a')sama dengan sizeof(int).

Di C ++, sizeof('a')sama dengan sizeof(char).


46
Itu dapat disederhanakan menjadi: Dalam C, 'a'adalah int. Dalam C ++, 'a'adalah a char.
pmg

38

C ++ juga memiliki kata kunci baru. Berikut ini adalah kode C yang valid tetapi tidak dapat dikompilasi di bawah C ++:

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

1
itu benar, tapi itulah arti dari subset.
yeyeyerman

20
@yeyeyerman: Tidak. Agar bisa menjadi subset, semua kode C juga harus valid C ++. Kode dalam contoh ini adalah C yang valid tetapi bukan C ++.
jalf

24
Tidak, jika C adalah subset dari C ++, maka setiap program C akan menjadi program C ++ yang valid, tapi itu tidak benar. Pertanyaannya adalah mengapa itu tidak benar, dan ini adalah salah satu contoh mengapa.
Graeme Perrow

Ha! Tidak memikirkan yang satu ini!
Gab Royer

20

Ada banyak hal. Hanya contoh sederhana (ini sudah cukup untuk membuktikan C bukan bagian yang tepat dari C ++):

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

harus dikompilasi dalam C tetapi tidak dalam C ++.


3
C ++ harus membutuhkan cast eksplisit ke int*.
Mehrdad Afshari

8
Jawaban panjang: malloc kembali void *, yang dalam C dapat ditetapkan ke jenis penunjuk apa pun, dan C ++ tidak dapat ditetapkan ke jenis penunjuk lainnya.
Daniel Earwicker

5
Imagist: kompiler C, seperti yang didefinisikan oleh standar ANSI C89, seharusnya tidak mengeluh.
Mehrdad Afshari

7
Ini legal C. Pemerannya tidak perlu, mungkin salah, dan menutupi kegagalan untuk menyertakan <stdlib.h>. Saya menganggap pernyataan Mehrdad sebagai cara yang tepat untuk menulisnya dalam C.
David Thornley

16
@Imagist: Saya biasanya mendengar kebalikan dari programmer C. Mereka menganggap itu gaya yang buruk untuk menambahkan pemeran, karena dapat menyembunyikan bug. Kode C yang baik tidak menggunakan pemeran.
jalf

16

Dalam C ++, jika Anda menyatakan struct, union, atau enum, namanya segera dapat diakses tanpa kualifikasi:

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

Di C, ini tidak akan berfungsi, karena tipe yang dideklarasikan tinggal di ruang nama yang berbeda. Jadi, Anda harus menulis:

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

Perhatikan keberadaan structsana di baris kedua. Anda harus melakukan hal yang sama untuk uniondan enum(menggunakan kata kunci masing-masing), atau menggunakan typedeftrik:

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

Akibatnya, Anda dapat memiliki beberapa jenis yang berbeda dengan nama yang sama di C, karena Anda dapat membedakan:

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

struct foo x;
foo y;

Namun, di C ++, meskipun Anda dapat memberi awalan structnama dengan kata kunci structsetiap kali Anda mereferensikannya, ruang nama tersebut digabungkan, sehingga potongan C di atas tidak valid. Di sisi lain, C ++ secara khusus membuat pengecualian untuk mengizinkan tipe dan typedef untuk tipe itu memiliki nama yang sama (jelas tidak berpengaruh), untuk memungkinkan penggunaan typedeftrik yang tidak diubah dari C.


1
Contoh terakhir Anda tidak valid C: Tiga tag ( struct, uniondan enum) berbagi namespace yang sama. Contoh yang lebih baik adalahstruct foo { ... }; typedef enum { ... } foo;
schot

@ Schot: Anda tentu saja benar, terima kasih atas koreksinya. Diperbarui.
Pavel Minaev

8

Ini juga tergantung pada jenis C yang Anda gunakan. Stroustrup membuat C ++ sekompatibel mungkin, dan tidak lebih kompatibel, dengan standar ANSI 1989 dan ISO 1990, dan versi 1995 tidak mengubah apa pun. Komite C mengambil arah yang agak berbeda dengan standar 1999, dan komite C ++ telah mengubah standar C ++ berikutnya (mungkin akan keluar tahun depan atau lebih) untuk menyesuaikan dengan beberapa perubahan.

Stroustrup mencantumkan ketidaksesuaian dengan C90 / C95 dalam Lampiran B.2 dari "The C ++ Programming Language", Edisi Khusus (yang merupakan edisi ke-3 dengan beberapa materi tambahan):

'a'adalah intdalam C, chardalam C ++.

Ukuran enum ada intdi C, tidak harus di C ++.

C ++ memiliki //komentar hingga akhir baris, C tidak (meskipun itu ekstensi umum).

Di C ++, struct foo {definisi diletakkan foodi namespace global, sedangkan di C harus disebut sebagai struct foo. Hal ini memungkinkan structdefinisi untuk membayangi nama di lingkup luar, dan memiliki beberapa konsekuensi lainnya. Selain itu, C memungkinkan cakupan yang lebih besar untuk structdefinisi, dan memungkinkannya dalam tipe pengembalian dan deklarasi tipe argumen.

C ++ lebih fussier tentang tipe secara umum. Ini tidak akan mengizinkan integer ditetapkan ke enum, dan void *objek tidak dapat ditetapkan ke jenis penunjuk lain tanpa cast. Di C, dimungkinkan untuk menyediakan penginisialisasi yang tumpang tindih (di char name[5] = "David"mana C akan membuang karakter nol yang tertinggal).

C89 mengizinkan implisit intdalam banyak konteks, dan C ++ tidak. Ini berarti bahwa semua fungsi harus dideklarasikan di C ++, sedangkan di C89 sering kali dimungkinkan dengan asumsi intuntuk semua yang berlaku dalam deklarasi fungsi.

Di C, dimungkinkan untuk melompat dari luar blok ke dalam menggunakan pernyataan berlabel. Di C ++, ini tidak diperbolehkan jika melewatkan inisialisasi.

C lebih liberal dalam hubungan eksternal. Di C, constvariabel global secara implisit extern, dan itu tidak benar di C ++. C memungkinkan objek data global untuk dideklarasikan beberapa kali tanpa extern, tapi itu tidak benar di C ++.

Banyak kata kunci C ++ bukan kata kunci dalam C, atau #defined dalam header C standar.

Ada juga beberapa fitur C lama yang tidak lagi dianggap sebagai gaya yang baik. Di C, Anda bisa mendeklarasikan fungsi dengan definisi argumen setelah daftar argumen. Di C, deklarasi like int foo()berarti yang foo()dapat menerima sejumlah jenis argumen apa pun, sedangkan di C ++ setara dengan int foo(void).

Itu sepertinya mencakup semuanya dari Stroustrup.


Jangan lupa fakta bahwa, di C, Anda harus mendeklarasikan variabel di awal ruang lingkup (yaitu, segera setelah kurung kurawal buka), sedangkan, C ++ mengizinkan deklarasi variabel di mana saja.
RobH

4
Namun, itu adalah sesuatu yang C ++ bisa lakukan yang tidak bisa dilakukan C. Saya pikir kami sedang melihat hal-hal yang dapat Anda lakukan di C tetapi tidak di C ++.
David Thornley

2
@ RobH: Itu benar untuk C89 tetapi tidak untuk C99.
jamesdlin

6

Jika Anda menggunakan gcc, Anda dapat menggunakan peringatan -Wc++-compatuntuk memberi Anda peringatan tentang kode C yang meragukan dalam C ++ dalam beberapa hal. Saat ini digunakan di gcc itu sendiri, dan menjadi jauh lebih baik akhir-akhir ini (mungkin coba versi nightly untuk mendapatkan yang terbaik yang Anda bisa).

(Ini tidak hanya menjawab pertanyaan, tetapi orang mungkin menyukainya).


1
Saya pikir saya tidak akan pernah
mendukung

4

Satu-satunya perbedaan terbesar yang menurut saya adalah ini adalah file sumber C yang valid:

int main()
{
    foo();
}

Perhatikan bahwa saya belum menyatakannya di foomana pun.

Selain perbedaan bahasa, C ++ juga membuat beberapa perubahan pada pustaka yang diwarisi dari C, misalnya beberapa fungsi kembali const char *daripada char *.


Benar, prototipe tidak diperlukan di C tetapi biasanya dianggap praktik yang buruk untuk tidak menggunakannya.
Robert Gamble

1
Anda harus melakukan s,C,C89,dan mencatat bahwa ini adalah file sumber C99 yang tidak valid.
Johannes Schaub - litb

Apakah itu tidak valid atau hanya usang di C99?
jalf

2
@jalf draf C99 mendokumentasikan perubahan ke C89, dan menyertakan "hapus int implisit" dan "hapus deklarasi fungsi implisit".
Johannes Schaub - litb


2

Sejumlah jawaban di sini mencakup perbedaan sintaks yang akan menyebabkan compiler C ++ gagal pada kode sumber C89 (atau C99). Namun, ada beberapa perbedaan bahasa halus yang legal di kedua bahasa tetapi akan menghasilkan perilaku yang berbeda. The sizeof (char)perbedaan itu Naveen disebutkan adalah salah satu contoh, tapi Tulis program yang akan mencetak "C" jika disusun sebagai (ANSI) C Program, dan "C ++" jika disusun sebagai program C ++ daftar beberapa orang lain.


-2

Kompiler C umumnya mengizinkan pemotongan sudut kecil yang tidak dilakukan C ++. C ++ jauh lebih ketat daripada C. Dan umumnya, beberapa perbedaan ini bergantung pada kompilator. g ++ mengizinkan beberapa hal yang tidak dimiliki kompiler Intel C ++, misalnya. Bahkan kode C yang ditulis dengan cukup baik tidak akan dapat dikompilasi dengan kompiler C ++ modern.


-2

Anda tidak dapat membandingkan bahasa hanya dengan sintaks. Jika Anda melakukan itu mungkin Anda bisa melihat C sebagai bagian dari C ++. Menurut pendapat saya, fakta bahwa C ++ adalah OO (dan C tidak) sudah cukup untuk mengatakan bahwa C dan C ++ adalah bahasa yang berbeda.


2
Salah. C ++ bukan hanya OO. Anda bisa berpikir C ++ seperti "C ++ = C + OO + pemrograman umum + bonus". Dengan kata lain, "C & C ++ ~ = C" di mana ~ = berarti hampir sama.
paercebal
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.