Apakah ada perbedaan antara foo (void) dan foo () dalam C ++ atau C?

253

Pertimbangkan dua definisi fungsi ini:

void foo() { }

void foo(void) { }

Apakah ada perbedaan antara keduanya? Jika tidak, mengapa voidargumennya ada? Alasan estetika?

Mendarat di
sumber
Karena C, Q / A ada di sini
Antti Haapala

Jawaban:

317

Dalam C :

  • void foo()berarti "suatu fungsi yang foomengambil jumlah argumen yang tidak ditentukan dari jenis yang tidak ditentukan"
  • void foo(void)berarti "suatu fungsi footanpa argumen"

Dalam C ++ :

  • void foo()berarti "suatu fungsi footanpa argumen"
  • void foo(void)berarti "suatu fungsi footanpa argumen"

Oleh foo(void)karena itu, dengan menulis , kami mencapai interpretasi yang sama di kedua bahasa dan membuat tajuk kami multibahasa (meskipun kami biasanya perlu melakukan beberapa hal lebih lanjut ke tajuk untuk membuat mereka benar-benar lintas-bahasa; yaitu, membungkusnya dalam extern "C"jika kami menyusun C ++).

DrPizza
sumber
10
Tetapi jika C ++ memerlukannya void, maka itu bisa menghindari masalah "yang paling menjengkelkan".
Adrian McCarthy
5
Benar, tetapi ada begitu banyak parsing jelek lainnya di C ++ tidak ada gunanya kvetching tentang salah satu dari mereka.
DrPizza
16
Pada pertanyaan terakhir, @James Kanze memposting berita menarik. Repost di sini untuk menghindari kehilangannya: versi pertama C tidak memungkinkan untuk menentukan jumlah parameter fungsi yang mungkin diambil, dengan demikian void foo()adalah satu-satunya sintaks untuk mendeklarasikan suatu fungsi. Ketika tanda tangan diperkenalkan, komite C harus mendisambiguasikan tidak ada parameter dari sintaks lama, dan memperkenalkan void foo(void)sintaksis. C ++ mengambilnya demi kompatibilitas.
Matthieu M.
3
Bisakah Anda memberi saya contoh C C90 dan nanti di mana menggunakan void foo()bukannya void foo(void)akan menghasilkan perbedaan fungsional? Yaitu saya telah menggunakan versi tanpa kekosongan selama bertahun-tahun dan tidak melihat masalah, apakah saya kehilangan sesuatu?
chacham15
6
@ chacham15 void foo() { if ( rand() ) foo(5); } mengkompilasi dan menjalankan (menyebabkan perilaku tidak terdefinisi kecuali Anda sangat beruntung), sedangkan void foo(void)dengan tubuh yang sama akan menyebabkan kesalahan kompilasi.
MM
39

Saya menyadari pertanyaan Anda berkaitan dengan C ++, tetapi ketika sampai pada C jawabannya dapat ditemukan di K&R, halaman 72-73:

Lebih lanjut, jika deklarasi fungsi tidak menyertakan argumen, seperti pada

double atof();

itu juga berarti bahwa tidak ada yang dapat diasumsikan tentang argumen atof; semua pemeriksaan parameter dimatikan. Arti khusus dari daftar argumen kosong ini dimaksudkan untuk mengizinkan program C lama untuk dikompilasi dengan kompiler baru. Tapi itu ide yang buruk untuk menggunakannya dengan program baru. Jika fungsi mengambil argumen, nyatakanlah; jika tidak membutuhkan argumen, gunakan void.

Kyle Cronin
sumber
Tetapi pertanyaannya adalah tentang definisi, dalam hal ini aturan C yang relevan adalah Daftar kosong dalam deklarator fungsi yang merupakan bagian dari definisi fungsi yang menentukan bahwa fungsi tidak memiliki parameter.
jinawee
9

C ++ 11 N3337 konsep standar

Tidak ada perbedaan.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

Lampiran C "Kompatibilitas" C.1.7 Klausa 8: deklarator mengatakan:

8.3.5 Ubah: Di C ++, fungsi yang dideklarasikan dengan daftar parameter kosong tidak membutuhkan argumen. Dalam C, daftar parameter kosong berarti bahwa jumlah dan jenis argumen fungsi tidak diketahui.

Contoh:

int f();
// means int f(void) in C ++
// int f( unknown ) in C

Dasar Pemikiran: Ini untuk menghindari panggilan fungsi yang salah (mis., Panggilan fungsi dengan nomor atau jenis argumen yang salah).

Efek pada fitur asli: Ubah ke semantik fitur yang terdefinisi dengan baik. Fitur ini ditandai sebagai "usang" dalam C.

8.5.3 fungsi mengatakan:

4. Parameter-deklarasi-klausa menentukan argumen yang dapat ditentukan, dan pemrosesan mereka, ketika fungsi dipanggil. [...] Jika klausa deklarasi-parameter kosong, fungsinya tidak membutuhkan argumen. Daftar parameter (kosong) sama dengan daftar parameter kosong.

C99

Seperti yang disebutkan oleh C ++ 11, int f() tidak menyebutkan apa pun tentang argumen, dan sudah usang.

Itu bisa mengarah ke kode kerja atau UB.

Saya telah menafsirkan standar C99 secara terperinci di: https://stackoverflow.com/a/36292431/895245

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
2

Di C, Anda menggunakan void dalam referensi fungsi kosong sehingga kompiler memiliki prototipe, dan prototipe itu memiliki "tidak ada argumen". Dalam C ++, Anda tidak perlu memberi tahu kompiler bahwa Anda memiliki prototipe karena Anda tidak dapat meninggalkan prototipe.

Paul Tomblin
sumber
1
"prototipe" berarti deklarasi daftar argumen dan jenis kembali. Saya mengatakan ini karena "prototipe" membingungkan saya tentang apa yang Anda maksudkan pada awalnya.
Zan Lynx