[Çözüldü] void pointer dönüşümü yapılması gerekli mi?

Başlatan blacksnow, 27 Haziran 2015 - 21:58:18

« önceki - sonraki »

0 Üyeler ve 2 Ziyaretçi konuyu incelemekte.

blacksnow

Merhaba, okuduğum bir kitapta c ile yazılmış girilen kelimeleri sıralayan bir program var.Programda bellekten dinamik olarak yer ayrılıyor ve sonunda boşaltılıyor.Boşaltılırken (void *) dönüşümü yapılıyor.Neden yapıldığını ve gerekli olup olmadığını merak ediyorum.

Not: Belirttiğim yer satirlaribas fonksiyonundadır.

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAKSSU 80 /* en buyuk satir uzunlugu */

typedef struct dugum { /* struct dugum'un tanimi  */
char  *satir; /* bilgi */
struct dugum  *sol, *sag;
} *dugumg;         /* dugumg tipinin tanimi*/

void *yeni (size_t d) /* bellek ayirma */
{
void *g;

if ((g=malloc(d))!=NULL)
return g; /* tamam */

fprintf(stderr, "SIRALA: Yetersiz bellek");
exit(1); /* programi kes */

} /* yeni */

size_t satiroku /* satir uzunlugu dondur; 0 dosya sonu */
(char *d, int u)
{
register char  *g = d;
register int  c;

while ((c=getchar())!='\n' && c!=EOF)        // enter'a basılmadıysa ve ctrl+d yapılmadıysa
if (u-->1)
*g++ = (char)c; /* daha uzun satirlari kes */

if (c==EOF && g==d)
return 0; /* bir sey okunamadi */

*g++ = '\0';
return g-d; /* asil uzunluk arti bir ('\0' icin) */

} /* satiroku */

void satirlaribas /* agacin ozcagrili taranmasi */
(dugumg g)
{
if (g!=NULL) {
satirlaribas(g->sol);
printf("%s\n", g->satir);
satirlaribas(g->sag);
free((void *)g->satir);       // dugum yapılarındaki satırlar için ayrılan yer boşaltılıyor
free((void *)g);                // burada yukarıdaki dugum yapısı için ayrılan yer boşaltılıyor
}                                           // ikisinde de (void *) dönüşümü yapılmış.
} /* satirlaribas */

int main (void)
{
char  satir[MAKSSU+1];  /* MAKSSU arti bir ('\0'  icin) */
size_t  su;                      /* simdiki satir uzunlugu */
dugumg  kok = NULL, *g;

while ((su=satiroku(satir,(int)sizeof satir)) > 0) {
g = &kok;
while (*g!=NULL) /* girilen kelimeleri karsilastirip, kucukse sol dugume, */
g = (strcmp(satir,(*g)->satir) < 0)                 /* buyukse sag dugume olacak sekilde "NULL" olana kadar karsilastirir */
? &(*g)->sol : &(*g)->sag;

*g = (dugumg) yeni(sizeof(struct dugum));
    strcpy((*g)->satir = (char *)yeni(su), satir);
(*g)->sol = (*g)->sag = NULL;
}

satirlaribas(kok);
return 0;

} /* main */

Reverser

Void pointer esneklik sağlaması açısından kullanılmış olabilir. Yani veri tipi hem integer hem char olarak kullanılabilir.

XFCE ROCKS !
Powered by Thunar & XFWM4



thoron

#2
free fonksiyonunun parametresi void*, reallocta olduğu gibi. Yani sen dönüşüm yapmasan da parametre olarak yazdığın pointer void*'a cast edilecektir. Ben yapmayı tercih ediyorum, yapmasan da olur tabi.

blacksnow

Cevaplarınız için teşekkür ederim.Aklıma bir soru daha takıldı.Şimdi free fonksiyonu void pointer parametresi alıyor yani int,long,char veya herhangi bir yapı türü için pointer olabilir, bunları bellekten silerken hangi tür olduğunun bilgisi gerekmiyor mu?Biz hepsini void pointer parametresi olarak alıyoruz.Program bunu nasıl biliyor?

Örneğin, char temizlerken 1 byte 1 byte, int için 4 byte 4 byte, void olduğunda nasıl oluyor?

thoron

#4
Alıntı yapılan: blacksnow - 27 Haziran 2015 - 22:55:12
Cevaplarınız için teşekkür ederim.Aklıma bir soru daha takıldı.Şimdi free fonksiyonu void pointer parametresi alıyor yani int,long,char veya herhangi bir yapı türü için pointer olabilir, bunları bellekten silerken hangi tür olduğunun bilgisi gerekmiyor mu?Biz hepsini void pointer parametresi olarak alıyoruz.Program bunu nasıl biliyor?

Örneğin, char temizlerken 1 byte 1 byte, int için 4 byte 4 byte, void olduğunda nasıl oluyor?

Gönderdiğiniz pointer allocate ettiği yerin başlangıç noktası. Ne kadar allocate ettiyse o pointerdan itibaren o kadar baytı serbest bırakıyor. Ne kadar allocate ettiğini nasıl biliyor derseniz, onu ben de merak ediyorum, bir ara bakarım diye not almıştım siz bunu sorunca hatırladım. Yalnız ben temizlemiyor, sadece ilgili alanı tekrar allocate edilebilir hale getiriyor veri üzerine bir şey yazılana kadar kalıyor diye biliyordum az önce baktım 0 koyuyor üzerine.

Bu arada allocate ederken 1, 4 falan yazmıyorsunuz umarım :) Sisteme göre değişiyor o boyutlar, sizeof fonksiyonu var ilgili değişkenin ne kadar yer kapladığını döndüren. Örn: int *i = (int*)malloc(sizeof(int))

blacksnow

@thoron, dediğinize göre sadece yeniden bellekten yer ayırılabilmesi için free fonksiyonu kaç byte ise o bölümü serbest bırakıyor.Eğer bu şekildeyse hangi tür olduğu önemsiz oluyor elbette.free fonksiyonuna giden adresler void pointer olarak alınıyor ve bu şekilde de esneklik sağlanıyor.

Biraz daha test ettim ve eğer char olursa ilk 8 adresi 0 yapıyor gerisini yapmıyor, int olursa 2 adresi 0 yapıyor.Bunun nedeni de benim bilgisayarımda int 4 byte, ilk 2 adres 8 byte ediyor.Diğer türlerde de ilk 8 byte temizleniyor diye tahmin ediyorum.Sonuç olarak sıfırlama önemli değil, önemli olan o bölgenin yeniden kullanılabilir olması sanırım.

Son olarak allocate ederken 1,4 falan yazmıyorum.Tekrardan teşekkürler :)