Saya menulis fungsi di mana saya ingin menerima 2 type
s parameter.
- A
string
(char *) - Di
structure
mana akan ada n jumlah elemen.
Dan untuk mencapai hal ini saya berpikir untuk menggunakan void *
tipe parameter yang sederhana . Tetapi saya tidak tahu bagaimana memverifikasi apakah parameternya adalah satu jenis atau yang lain, aman.
void*
poin.func_str
danfunc_struct
dan mendapatkan pemeriksaan jenis pada waktu kompilasi._Generic
makro. Anda juga dapat membuat jenis pengenal diri, misalnya dengan serikat yang ditandai , yang berarti bahwa Anda tidak dapat melewatkanchar *
string mentah . Semua itu mungkin lebih banyak masalah daripada nilainya.Jawaban:
Terjemahan
void*
adalah"terhormat compiler, ini adalah pointer, seorang tidak ada informasi tambahan untuk Anda dalam hal ini.".
Biasanya kompiler tahu lebih baik daripada Anda (programmer), karena informasi yang ia dapatkan sebelumnya dan masih ingat dan Anda mungkin sudah lupa.
Tetapi dalam kasus khusus ini, Anda lebih tahu atau perlu tahu lebih baik. Dalam semua kasus
void*
informasi tersedia sebaliknya, tetapi hanya untuk programmer, yang "kebetulan tahu". Pemrogram karenanya harus memberikan informasi kepada kompiler - atau lebih baik untuk menjalankan program, karena satu kelebihan yangvoid*
dimiliki adalah bahwa informasi dapat berubah selama runtime.Biasanya itu dilakukan dengan memberikan informasi melalui parameter tambahan ke fungsi, kadang-kadang melalui konteks, yaitu program "kebetulan tahu" (misalnya untuk setiap jenis yang mungkin ada fungsi yang terpisah, mana fungsi yang dipanggil menyiratkan jenis).
Jadi pada akhirnya
void*
tidak berisi info jenis.Banyak programmer salah memahami hal ini sebagai "Saya tidak perlu tahu tipe info".
Tetapi yang sebaliknya adalah benar, penggunaan
void*
meningkatkan tanggung jawab programmer untuk melacak tipe info dan memberikannya secara tepat ke program / kompiler.sumber
void*
fungsi, pilih tipe yang salah, lalu hapus referensi datanya ... maka semua jenis perilaku tidak terdefinisi dipanggil.void*
agak usang untuk pemrograman generik, tidak ada banyak situasi di mana Anda harus menggunakannya saat ini. Mereka berbahaya karena menyebabkan keamanan tipe yang tidak ada. Dan seperti yang Anda catat, Anda juga kehilangan informasi jenis, yang berarti Anda harus menyeret beberapa rumitenum
bersama denganvoid*
.Sebagai gantinya Anda harus menggunakan C11
_Generic
yang dapat memeriksa jenis pada waktu kompilasi dan menambahkan keamanan jenis. Contoh:Ingatlah untuk menyediakan
const
versi yang memenuhi syarat ( ) dari semua jenis yang ingin Anda dukung.Jika Anda ingin kesalahan kompiler yang lebih baik ketika pemanggil melewati tipe yang salah, Anda bisa menambahkan pernyataan statis:
Jika Anda mencoba sesuatu seperti
int x; func(x);
Anda akan mendapatkan pesan kompiler"x: incorrect type"
.sumber