Mengapa tipe void C tidak analog dengan tipe kosong / bawah?

28

Wikipedia serta sumber lain yang saya temukan daftar voidtipe C sebagai tipe unit sebagai lawan dari tipe kosong. Saya menemukan ini membingungkan karena menurut saya voidlebih cocok dengan definisi tipe kosong / bawah.

  • Tidak ada nilai yang dihuni void, sejauh yang saya tahu.
  • Suatu fungsi dengan tipe kembali dari kekosongan menentukan bahwa fungsi tidak mengembalikan apa pun dan dengan demikian hanya dapat melakukan beberapa efek samping.
  • Pointer tipe void*adalah subtipe dari semua tipe pointer lainnya. Juga, konversi ke dan dari void*dalam C adalah implisit.

Saya tidak yakin apakah poin terakhir memiliki kelebihan sebagai argumen untuk voidmenjadi tipe kosong, seperti void*lebih atau kurang kasus khusus dengan tidak banyak hubungannya dengan void.

Di sisi lain, voiditu sendiri bukan subtipe dari semua jenis lainnya, yang sejauh yang saya tahu adalah persyaratan untuk jenis menjadi tipe bawah.

Meta
sumber
10
Dengan "tidak mengembalikan apa pun" Anda sebenarnya berarti "tidak mengembalikan apa pun yang menarik", sedangkan fungsi dengan output kosong tidak kembali sama sekali (yaitu crash atau loop tak terhingga).
Turion
2
Sebagai tipe pengembalian, void adalah tipe unit.
user253751

Jawaban:

38

Dalam C, voiddigunakan untuk banyak hal yang tidak terkait. Bergantung pada apa yang digunakan untuk itu, artinya mungkin tipe unit, tipe kosong, atau sesuatu yang lain.

Ketika voiddigunakan dengan sendirinya (sebagai lawan dari void*, pointer ke void), itu adalah tipe unit, yaitu tipe dengan nilai tunggal. Fungsi yang mengembalikan voiddikatakan “tidak menghasilkan apa-apa”, tetapi yang sebenarnya berarti adalah bahwa mereka tidak mengembalikan informasi apa pun. Mereka mengembalikan bit informasi, yang berarti bahwa mereka mengembalikan nilai dari tipe yang mengandung 2 0 = 1 nilai yang berbeda, yaitu tipe unit.020=1

Ini bukan tipe kosong: fungsi yang mengembalikan tipe kosong tidak dapat mengembalikan nilai, karena tidak ada nilai tipe itu. Fungsi yang tipe pengembaliannya kosong hanya dapat diulang selamanya, atau dibatalkan programnya, atau menimbulkan pengecualian ( longjmp) (atau mengatur agar tidak kembali, misalnya dengan mentransfer kontrol ke utas lain atau proses menggunakan fungsionalitas di luar standar C). Untuk membuat hal-hal membingungkan, itu konvensional dalam C untuk digunakan voidsebagai pengganti tipe kosong (C tidak memiliki tipe kosong).

The voidTipe membutuhkan bit penyimpanan. Karena C bersikeras pada setiap objek yang menempati keseluruhan, jumlah byte penyimpanan yang tidak nol, dilarang membuat objek bertipe , dan ada sintaks khusus untuk mengembalikan nilai ( pernyataan dengan nilai yang dihilangkan). Tidak ada sintaks yang menghasilkan nilai tipe , tetapi nilai itu ada setiap kali fungsi yang tipe pengembaliannya dikembalikan.0voidvoidreturnvoidvoid

C tidak memiliki tipe dasar dalam arti memungkinkan tipe apa pun yang mungkin. Bahkan tipe yang tidak lengkap menentukan sifat umum dari nilai-nilainya, misalnya pointer atau struct atau serikat atau fungsi. Tetapi void*adalah pointer ke semua jenis non-fungsi: itu adalah elemen paling sedikit dari aljabar jenis pointer objek, yaitu itu adalah tipe pointer objek bawah. Berbeda dengan kasus umum di T*mana Tada beberapa tipe non-void, void*bukan tipe pointer ke nilai tipe void, tetapi tipe pointer ke nilai tipe yang tidak ditentukan.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Satu dapat mengembalikan void di C ++ dan C89. stackoverflow.com/questions/35987493/…
BartekChom
2
Paragraf 4 secara resmi salah. Dalam C, jumlah penyimpanan untuk voidtidak ditentukan, bukan nol. Ini bukan alasan mengapa objek bertipe voidtidak diizinkan. Alasan formal adalah bahwa itu voidadalah tipe yang tidak lengkap , dan objek tidak dapat memiliki tipe yang tidak lengkap.
MSalters
4
@ MSalters Tidak, apa yang saya tulis secara resmi benar. "Karena" mengacu pada motivasi untuk desain bahasa, bukan pada kesimpulan logis di dalam spesifikasi bahasa. The voidTipe membutuhkan 0 bit penyimpanan. Ini adalah alasan mengapa para perancang C memutuskan untuk membuat voidtipe yang tidak lengkap, sebagai lawan dari mendefinisikannya mengambil 0 byte penyimpanan (yang akan memiliki banyak dampak pada desain bahasa) atau 1 byte penyimpanan (yang akan membuang-buang ruang) .
Gilles 'SO- stop being evil'
1
@Gilles: Maaf, tapi itu juga tidak masuk akal. Jika diizinkan, ruang yang digunakan adalah 1 byte per objek dari tipe void , dan Anda jelas tidak membutuhkan banyak objek voidtipe. Belum lagi benda-benda ini bisa alias semua benda lain, jadi penggunaan sebenarnya akan menjadi nol.
MSalters
4
@CodesInChaos: Ya, C ++ sebenarnya memungkinkan struct kosong, yaitu struct E { };. Ketika digunakan sebagai kelas dasar, ini bisa berukuran nol. (Benar-benar tidak ada yang namanya C / C ++, kedua bahasa membuat pilihan mereka sendiri dan mereka dapat berbeda di daerah ini. C jelas tidak memiliki kelas dasar yang kosong, karena tidak memiliki OO di tempat pertama)
MSalters
11

Nama "tipe kosong" mungkin membingungkan. Apa artinya ini, seperti yang Anda katakan sendiri, jenisnya tidak mengandung nilai . "Kosong" mengacu bukan pada nilai individu dari jenis, itu mengacu pada jenis secara keseluruhan, dianggap sebagai ~ set nilai yang mungkin. Jadi ini tidak mengatakan sesuatu seperti "fungsi yang voidmengembalikan tidak ada informasi", tetapi "tidak ada nilai tipe ".

Ini berarti suatu fungsi yang tipe hasilnya tidak pernah dapat berakhir. Jika itu benar-benar berakhir, jika harus mengembalikan nilai , tetapi, well, nilai seperti itu tidak ada.

Ini juga berarti, bahkan tidak mungkin untuk membahas berapa banyak informasi yang akan berisi nilai dari tipe kosong, karena tidak ada nilai seperti itu. (Atau jika Anda mau, pernyataan tidak masuk akal seperti "nilai apa pun dari jenis kosong mengandung persis 35093658 bit informasi" adalah benar-benar kosong.) Agak berguna (meskipun tidak benar-benar benar) untuk menganggap nilai mengandung informasi yang tak terbatas .

Sedangkan fungsi C dengan "tipe pengembalian" voidjelas dapat kembali, tetapi tidak memberi Anda informasi dalam nilai pengembaliannya. Ya, itulah yang menjadi ciri khas tipe unit: nilainya tidak mengandung informasi apa pun, karena hanya ada satu nilai seperti itu (maka Anda selalu dapat mengatakan apa nilai pengembaliannya, bahkan tanpa repot-repot memanggil fungsi).

Mengutip Conor McBride (diterjemahkan ke C):

voidberarti "Membosankan". Artinya tipe membosankan yang mengandung satu hal, juga membosankan. Tidak ada yang menarik untuk diperoleh dengan membandingkan satu elemen dari tipe membosankan dengan yang lain, karena tidak ada yang perlu dipelajari tentang elemen dari tipe membosankan dengan memberikannya perhatian Anda.

Ini sangat berbeda dari tipe kosong [...]. Jenis kosong sangat menarik, karena jika seseorang pernah memberi Anda nilai miliknya, Anda tahu bahwa Anda sudah mati dan di Surga dan bahwa apa pun yang Anda inginkan adalah milik Anda.

leftaroundabout
sumber
Menarik; jika definisi ⊥ adalah fungsi yang tipe kembaliannya ⊥ tidak pernah bisa berakhir, maka C memiliki tipe seperti itu. Kami menyebutnya volatile void.
Yosua
Menarik, saya tidak tahu itu. Saya tampaknya tidak benar-benar memenuhi standar .
leftaroundabout