Saya membaca buku ( Pemrograman dengan POSIX Threads oleh Butenhof, 1997) yang menggunakan C, dan saya menemukan baris berikut:
(void)free(data);
Di sini, data
hanya sebuah pointer ke struct yang dialokasikan,
data = malloc(sizeof(my_struct_t));
Mengapa akibat free
dilemparkan void
?
Dari pemahaman saya tentang C, ini sepertinya tidak masuk akal karena dua alasan:
- Fungsi gratis sudah kembali
void
- Kode tidak menggunakan nilai kembali (bahkan tidak ditugaskan ke variabel)
Buku itu ditulis pada tahun 1997. Apakah ini semacam warisan?
Penulis menyebutkan bahwa contoh dijalankan di Digital Unix 4.0d, tapi saya masih tidak bisa membayangkan alasan untuk pernah melemparkan hasil fungsi jika Anda tidak akan menggunakan hasil itu.
free()
sebagai keanehan dalam buku yang tidak perlu Anda tiru. Itu semi-relevan dulu sekali, tapi itu tidak relevan lagi.Jawaban:
Jika kita berbicara tentang
free
fungsi standar maka prototipenya adalahKarena itu para pemain sama sekali tidak berguna.
Sekarang beberapa spekulasi.
Penulis mungkin lupa menyertakan
stdlib.h
header yang menyatakan prototipe ini, sehingga kompiler menganggap tipe kembalinya sebagaiint
. Sekarang selama analisis statis kode ini kompiler memperingatkan tentang nilai balik yang tidak terpakai dari apa yang dianggapnya sebagai tidakvoid
berfungsi. Peringatan seperti itu biasanya dibungkam dengan menambahkan pemeranvoid
.sumber
free
dari yang sebenarnya, dengan hasil bahwa panggilan memiliki perilaku yang tidak terdefinisi (seandainya C90 semantik, di mana memanggil fungsi yang tidak dideklarasikan secara inheren tidak menunjukkan UB dalam semua kasus). Dalam prakteknya, adalah masuk akal bahwa yang akan mengakibatkan bona fide perilaku pada beberapa sistem. Solusi yang benar adalah dengan memberikan deklarasi yang benar untuk fungsi tersebut.Itu akan menjadi warisan!
Sebelum ada standar C,
free()
fungsinya adalah tipe (secara implisit)int
- karena belum ada tipe yang dapat diandalkanvoid
untuk mengembalikannya. Tidak ada nilai yang dikembalikan.Ketika kode pertama kali dimodifikasi untuk bekerja dengan kompiler C standar, mungkin tidak termasuk
<stdlib.h>
(karena tidak ada sebelum standar). Kode lama akan menulisextern char *malloc();
(mungkin tanpaextern
) untuk fungsi alokasi (sama untukcalloc()
danrealloc()
), dan tidak perlu mendeklarasikanfree()
. Dan kode kemudian akan melemparkan nilai kembali ke jenis yang benar - karena itu diperlukan pada setidaknya beberapa sistem (termasuk yang saya pelajari C on).Beberapa waktu kemudian, para
(void)
pemain ditambahkan untuk memberi tahu kompiler (atau, lebih mungkin,lint
) bahwa "nilai pengembalian darifree()
sengaja diabaikan" untuk menghindari keluhan. Tetapi akan lebih baik untuk menambahkan<stdlib.h>
dan membiarkan deklarasiextern void free(void *vp);
memberitahulint
atau kompiler bahwa tidak ada nilai untuk diabaikan.JFTR: Kembali pada pertengahan '80 -an, ICL Perq awalnya pada arsitektur berorientasi kata dan
char *
alamat untuk lokasi memori adalah nomor yang sangat berbeda dari 'penunjuk apa saja' ke lokasi yang sama. Sangat penting untuk mendeklarasikanchar *malloc()
entah bagaimana; itu penting untuk melemparkan hasilnya dari itu ke jenis pointer lainnya. Para pemain sebenarnya mengubah angka yang digunakan oleh CPU. (Ada juga banyak kegembiraan ketika memori utama pada sistem kami ditingkatkan dari 1 MiB menjadi 2 MiB - karena kernel menggunakan sekitar 3/4 MiB, itu berarti bahwa program pengguna dapat menggunakan 1 1/4 MiB sebelum paging dll.)sumber
free()
pada hal. 177 yang secara implisit kembaliint
.void
ditambahkan ke beberapa sistem (Unix System III, mungkin) sebelum standar dirilis, tetapi itu bukan bagian dari C ketika K&R 1st Edn ditulis (1978). Fungsi yang tidak mengembalikan nilai dinyatakan tanpa tipe pengembalian (yang artinya dikembalikanint
), dan selama Anda tidak menggunakan nilai yang tidak dikembalikan, tidak ada masalah. Standar C90 harus memperlakukan kode semacam itu sebagai valid - standar itu akan gagal jika standar tidak gagal. Tapi C99 menghapus aturan 'implisitint
' dan 'deklarasi fungsi implisit'. Tidak semua kode di dunia berhasil menyusul.(void)
gips untukprintf()
??Pemain ini tidak diperlukan. Mungkin tidak akan pada saat itu karena C telah distandarisasi dalam bentuk C89.
Jika sudah, itu pasti karena deklarasi implisit . Ini biasanya berarti bahwa orang yang menulis kode lupa
#include <stdlib.h>
dan penganalisa statis sedang digunakan. Ini bukan solusi terbaik dan ide yang jauh lebih baik untuk menjadi hanya#include <stdlib.h>
sebagai gantinya. Inilah beberapa kata dari C89 tentang deklarasi implisit:Tapi itu aneh karena mereka tidak menampilkan hasil dari
malloc
keduanya, danmalloc
danfree
berada di file header yang sama.Mungkin juga ini hanya kesalahan atau cara untuk memberitahu pembaca bahwa
free
tidak ada hasil.sumber
free
tetapi tidak untukmalloc
.