Saya memasang gips hanya untuk menunjukkan ketidaksetujuan lubang jelek di sistem tipe, yang memungkinkan kode seperti cuplikan berikut untuk dikompilasi tanpa diagnostik, meskipun tidak ada gips yang digunakan untuk menghasilkan konversi yang buruk:
double d;
void *p = &d;
int *q = p;
Saya berharap itu tidak ada (dan tidak ada di C ++) dan jadi saya melemparkan. Ini mewakili selera saya, dan politik pemrograman saya. Saya tidak hanya memberikan pointer, tetapi secara efektif, memberikan suara, dan mengusir setan kebodohan . Jika saya tidak bisa benar - benar mengusir kebodohan , maka setidaknya izinkan saya mengungkapkan keinginan untuk melakukannya dengan isyarat protes.
Bahkan, praktik yang baik adalah membungkus malloc
(dan teman) dengan fungsi yang kembali unsigned char *
, dan pada dasarnya tidak pernah digunakan void *
dalam kode Anda. Jika Anda memerlukan penunjuk generik ke objek apa pun, gunakan a char *
atau unsigned char *
, dan gips ke kedua arah. Satu relaksasi yang bisa dimanjakan, mungkin, adalah menggunakan fungsi suka memset
dan memcpy
tanpa gips.
Pada topik casting dan kompatibilitas C ++, jika Anda menulis kode Anda sehingga dikompilasi sebagai C dan C ++ (dalam hal ini Anda harus memberikan nilai pengembalian malloc
ketika menugaskannya ke sesuatu selain void *
), Anda dapat melakukan yang sangat membantu hal untuk diri sendiri: Anda dapat menggunakan makro untuk casting yang menerjemahkan ke gaya C ++ saat dikompilasi sebagai C ++, tetapi kurangi menjadi cast C saat mengkompilasi sebagai C:
/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif
Jika Anda mematuhi makro ini, maka grep
pencarian sederhana dari basis kode Anda untuk pengidentifikasi ini akan menunjukkan kepada Anda di mana semua gips Anda, sehingga Anda dapat meninjau apakah ada yang salah.
Kemudian, maju, jika Anda secara teratur mengkompilasi kode dengan C ++, itu akan memberlakukan penggunaan pemain yang sesuai. Misalnya, jika Anda menggunakan strip_qual
hanya untuk menghapus a const
atau volatile
, tetapi program berubah sedemikian rupa sehingga konversi jenis sekarang terlibat, Anda akan mendapatkan diagnostik, dan Anda harus menggunakan kombinasi gips untuk mendapatkan konversi yang diinginkan.
Untuk membantu Anda mematuhi makro ini, kompiler GNU C ++ (bukan C!) Memiliki fitur yang indah: diagnostik opsional yang dibuat untuk semua kejadian cetakan gaya C.
-Wold-style-cast (khusus C ++ dan Objective-C ++)
Peringatkan jika gaya lama (gaya-C) digunakan untuk tipe non-void
dalam program C ++. Gips gaya baru (dynamic_cast,
static_cast, reinterpret_cast, dan const_cast) kurang rentan
untuk efek yang tidak diinginkan dan lebih mudah untuk mencari.
Jika kode C Anda dikompilasi sebagai C ++, Anda dapat menggunakan -Wold-style-cast
opsi ini untuk mengetahui semua kemunculan (type)
sintaks casting yang dapat masuk ke dalam kode, dan menindaklanjuti diagnostik ini dengan menggantinya dengan pilihan yang sesuai dari antara makro di atas (atau kombinasi, jika perlu).
Perlakuan konversi ini adalah pembenaran teknis mandiri tunggal terbesar untuk bekerja dalam "Clean C": dialek C dan C ++ gabungan, yang pada gilirannya secara teknis membenarkan penuangan nilai kembali malloc
.