Saya sedang bekerja pada basis kode lama dan hampir setiap doa gratis () menggunakan gips pada argumennya. Sebagai contoh,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
di mana setiap pointer adalah tipe yang sesuai (dan cocok). Saya tidak melihat gunanya melakukan ini sama sekali. Itu kode yang sangat lama, jadi saya bertanya-tanya apakah ini masalah K&R. Jika demikian, saya sebenarnya ingin mendukung kompiler lama yang mungkin membutuhkan ini, jadi saya tidak ingin menghapusnya.
Apakah ada alasan teknis untuk menggunakan gips ini? Saya bahkan tidak melihat banyak alasan pragmatis untuk menggunakannya. Apa gunanya mengingatkan diri kita tentang tipe data sebelum membebaskannya?
EDIT: Pertanyaan ini bukan duplikat dari pertanyaan lain. Pertanyaan lain adalah kasus khusus dari pertanyaan ini, yang saya pikir jelas jika pemilih dekat akan membaca semua jawaban.
Colophon: Saya memberi "const answer" tanda centang karena itu adalah alasan nyata mengapa hal ini perlu dilakukan; Namun, jawaban tentang hal itu menjadi kebiasaan pra-ANSI C (setidaknya di antara beberapa programmer) tampaknya menjadi alasan itu digunakan dalam kasus saya. Banyak poin bagus oleh banyak orang di sini. Terima kasih atas kontribusi kamu.
void*
dalam standar C, tetapi hanyachar*
. Jadi jika temuan arkeologis Anda mengungkapkan kode yang melepaskan parameter ke (), saya percaya itu harus dari periode waktu itu, atau ditulis oleh makhluk dari waktu itu. Saya tidak dapat menemukan sumber untuk ini, jadi saya akan menahan diri untuk tidak menjawab.Jawaban:
Casting mungkin diperlukan untuk menyelesaikan peringatan kompiler jika petunjuknya adalah
const
. Berikut adalah contoh kode yang menyebabkan peringatan tanpa melemparkan argumen gratis:Dan kompiler (gcc 4.8.3) mengatakan:
Jika Anda menggunakan
free((float*) velocity);
kompiler berhenti mengeluh.sumber
float*
sebelum membebaskan. Saya mencobafree((void *)velocity);
dengan gcc 4.8.3. Tentu saja itu tidak akan berfungsi dengan kompiler kunoconst char *p
sebagai argumen dan kemudian membebaskan itu, hal yang benar untuk dilakukan adalah untuk tidak corp
untukchar*
sebelum menelepon gratis. Ini untuk tidak mendeklarasikannya sebagai mengambilconst char *p
tempat, karena itu memodifikasi*p
dan harus dinyatakan sesuai. (Dan jika membutuhkan pointer const bukan pointer ke const,int *const p
Anda tidak perlu melakukan cast karena itu benar-benar legal dan dengan demikian berfungsi dengan baik tanpa cast.)Pra-standar C tidak memiliki
void*
tetapi hanyachar*
, sehingga Anda harus membuang semua parameter yang dilewati. Jika Anda menemukan kode C kuno, karena itu Anda mungkin menemukan gips tersebut.Pertanyaan serupa dengan referensi .
Ketika standar C pertama dirilis, prototipe untuk malloc dan bebas berubah dari keharusan
char*
kevoid*
yang mereka miliki saat ini.Dan tentu saja dalam standar C, gips seperti itu berlebihan dan hanya membahayakan keterbacaan.
sumber
free
tipe yang sama seperti yang sudah ada?free
bekerja dalam standar C (Anda tidak perlu melakukan cast). Saya belum membaca edisi 1 jadi saya tidak tahu apakah mereka bingung di era pra-standar 80-an juga.void*
, tetapi tidak memiliki prototipe fungsi juga, jadi melemparkan argumenfree
masih tidak perlu bahkan di K&R (dengan asumsi semua tipe data pointer menggunakan representasi yang sama).char *
. Apa artinya masuk kompiler lama tanpavoid
? Apa yang akan dicapai oleh para pemain seperti itu?Berikut adalah contoh di mana gratis akan gagal tanpa gips:
Dalam C Anda bisa mendapatkan peringatan (mendapatkannya di VS2012). Di C ++ Anda akan mendapatkan kesalahan.
Mengesampingkan kasus langka, casting hanya menggembungkan kode ...
Sunting: Saya memilih untuk
void*
tidakint*
menunjukkan kegagalan. Ini akan bekerja sama seperti yangint*
akan dikonversivoid*
secara implisit.int*
Kode ditambahkan .sumber
void *
, tetapi kefloat *
danchar *
. Para pemain tidak hanya asing, mereka salah.free(p)
gagal? Apakah akan memberikan kesalahan kompiler?const
pointer kualifikasi, tentu saja.volatile
telah ada sejak C dibakukan jika tidak lagi. Itu tidak ditambahkan di C99.Alasan lama: 1. Dengan menggunakan
free((sometype*) ptr)
, kode eksplisit tentang jenis pointer harus dianggap sebagai bagian darifree()
panggilan. Pemeran eksplisit berguna ketikafree()
diganti dengan (do-it-yourself)DIY_free()
.A
DIY_free()
adalah cara, terutama dalam mode debug, untuk melakukan analisis run-time dari pointer yang dibebaskan. Ini sering dipasangkan dengan aDIY_malloc()
untuk menambahkan sentensial, jumlah penggunaan memori global, dll. Grup saya menggunakan teknik ini selama bertahun-tahun sebelum alat yang lebih modern muncul. Itu berkewajiban bahwa item yang dibebastugaskan dilemparkan ke jenis awalnya dialokasikan.Modern: Menghindari
const
danvolatile
memperingatkan seperti yang disampaikan oleh Manos Nikolaidis @ dan @egur . Pikir saya akan perhatikan efek dari 3 kualifikasi :const
,volatile
, danrestrict
.[sunting] Ditambahkan
char * restrict *rp2
per @R .. komentarsumber
restrict
hanya masalah karena di mana ia ditempatkan - itu mempengaruhi objekrp
bukan tipe-menunjuk-ke. Jika Anda malah melakukannyachar *restrict *rp
, maka itu penting.Berikut adalah hipotesis alternatif lain.
Kami diberitahu bahwa program ini ditulis pra-C89, yang berarti tidak dapat mengatasi semacam ketidakcocokan dengan prototipe
free
, karena tidak hanya tidak ada hal seperticonst
atauvoid *
sebelum C89, tidak ada yang namanya sebuah prototipe fungsi sebelum C89.stdlib.h
sendiri adalah penemuan komite. Jika header sistem repot untuk mendeklarasikanfree
sama sekali, mereka akan melakukannya seperti ini:Sekarang, titik kunci di sini adalah bahwa tidak adanya prototipe fungsi berarti kompiler tidak memeriksa jenis argumen . Itu menerapkan promosi argumen default (yang sama yang masih berlaku untuk panggilan fungsi variadic) dan hanya itu. Tanggung jawab untuk membuat argumen di setiap callsite sesuai dengan harapan callee sepenuhnya berada di tangan programmer.
Namun, ini masih tidak berarti perlunya mengajukan argumen
free
pada kebanyakan penyusun K&R. Fungsi sepertiseharusnya dikompilasi dengan benar. Jadi saya pikir apa yang kita punya di sini adalah program yang ditulis untuk mengatasi kompiler kereta untuk lingkungan yang tidak biasa: misalnya, lingkungan di mana
sizeof(float *) > sizeof(int)
dan kompiler tidak akan menggunakan konvensi pemanggilan yang sesuai untuk pointer kecuali jika Anda melemparkan mereka pada titik panggilan.Saya tidak mengetahui adanya lingkungan seperti itu, tetapi itu tidak berarti tidak ada. Calon yang paling mungkin muncul dalam pikiran adalah kompiler "kecil C" yang dipotong untuk micros 8 dan 16 bit pada awal 1980-an. Saya juga tidak akan terkejut mengetahui bahwa Crays awal memiliki masalah seperti ini.
sumber
gratis hanya mengambil pointer non-const sebagai parameter. Jadi dalam kasus pointer pointer, casting eksplisit ke pointer non-const diperlukan.
Tidak dapat membebaskan pointer const di C
sumber