İşaretçi dönüşümü, C dilinde sık karşılaşılan bir işlemdir ve genel arayüzler kullanmamıza, örneğin, void* üzerinden bellekle çalışmaya veya evrensel veri yapılarını uygulamaya olanak tanır. Ancak işaretçi türlerini dönüştürmenin bazı riskleri vardır ve sıkı standartlara tabidir.
void* C dilinde bir adresi saklar fakat hangi türde içerik gösterdiğini bilmez. Herhangi bir diğer işaretçi (örneğin, int*, char*, struct mytype*) açıkça (veya örtük olarak) void*'ye ve geri dönüştürülebilir, bilgi kaybı olmadan ("daraltma" olmazsa).void process(void *data) { int *arr = (int*)data; // arr'yi int dizisi olarak kullanırız } int main() { double x = 10; process(&x); // TEHLİKELİ: double*'yi int*'ye dönüştürüyoruz, UB }
"Herhangi bir işaretçi güvenle void*'ye ve geri dönebilir mi?"
Birçok kişi "evet" der — çünkü C standardı her nesne işaretçisinin void*'ye ve geri dönüşümünü kayıpsız dönüştürmeyi garanti eder. Ancak hatırlamak önemlidir: eğer bir nesne olmayan işaretçiyi (örneğin, bir fonksiyon işaretçisini) void*'ye dönüştürürseniz veya farklı mimarileri karıştırırsanız (işaretçi boyutları işlevler ve veriler için farklıdır), belirsiz davranış elde edersiniz.
void foo() {} void *p = (void*)foo; // UB! Fonksiyon işaretçisi böyle dönüştürülemez
Hikaye
Veri işleme için çapraz platform bir alt sistem projesinde, bir işaretçiyi yapıya dönüşüme
void*'ye dönüştüren ve ardından orijinal türe geri döndüren bir işleyici kullandık. 'int*' ve 'double*' için farklı hizalamaların olduğu bir mimariye geçildiğinde,void*'yi hatalı bir türde dönüştürmeye çalışmak "bus error" (açık kapanma) ile sona erdi.
Hikaye
Bir embedded projede, programcı
void*üzerinde evrensel bir arayüz ile bir dairesel tampon uyguladı, fakat hizalama gereksinimlerini unuttu (belleğichardizisi olarak ayırdı,int*olarak geçirdi). Bazı platformlarda, veriler "donanım tarafından anlaşılamıyordu" — okuma hataları ve kararsız çalışma meydana geldi.
Hikaye
Dinamik bir koleksiyonda adresleri
void*olarak sakladık ama fonksiyon işaretçisininvoid*'ye dönüştürülemeyeceğini unuttuk. Olay işleyicisini (callback) böyle bir alan üzerinden saklama ve geçirme çabası yalnızca bazı platformlarda hatalara yol açtı ve hatayı yakalamak son derece zor oldu.