C Dinamik Diziler

C ve C++ programlama dillerinde dinamik bellek yönetimi, dinamik dizi oluşturma, kullanma ve yönetimi ile ilgili bilgiler yer alıyor.

Dinamik dizi nedir?

Dizi boyutunun programın çalışması sırasında artması veya azalmasıdır.

C ve C++ programlama dillerinde bellek yönetimi derleme ve çalışma zamanı olmak üzere iki farklı zamanda olur.

Aşağıdaki gibi bir tanımlamada derleyici derleme zamanında belleğin stack bölgesinden 10 elemanlı bir alan ayıracaktır.

int elemanSayisi = 10;
int sayilar[elemanSayisi];
printf("%d", sizeof(sayilar));

Ancak geliştirilen uygulamalarda elaman sayısı tam belli olmayabilir veya kullanıcıdan alınan değere göre değişiklik gösterebilir.

Bu durumda calloc, malloc, realloc ve free fonksiyonları ile belleğin heap bölgesinden yer ayrırarak dinamik bellek yönetimi yapılır.

Dinamik bellek yönetimi

Dinamik bellek yönetimi için kullanılacak veri yapısına uygun bir işaretçi tanımlanması gerekir.

int *sayilar;

Dinamik bellek yönetimi fonksiyonları ile işletim sisteminden bellek tahsisi talep edilir.

calloc(10, sizeof(int));
veya
malloc(10 * sizeof(int));

İşletim sistemi bellek tahsisini bellek yeterli ise yapar yeterli değilse 0 veya NULL değerini verir.

İşletim sistemi bellek alanı ayırsa bile biz bu alanı doğrudan kullanamayız.

Bu alanı kullanabilmek için işaretçi değişken ile ayrılan bellek alanının aşağıdaki gibi referans verilmesi gerekir.

int elemanSayisi = 10;
int *sayilar;

//sayilar = calloc(elemanSayisi, sizeof(int));
sayilar = malloc(elemanSayisi * sizeof(int));

Bellek alanını ayrılıp ayrılmadığının kontrol edilmesi ve belleğin serbest bırakılması faydalı olacaktır.

int elemanSayisi = 10;
int *sayilar;

sayilar = malloc(elemanSayisi * sizeof(int));

if( sayilar == NULL)
    fprintf(stdout, "Hata olustu");
else
    fprintf(stdout, "Bellek alani tahsis edildi.");

free(sayilar);

Dinamik diziler

Dinamik dizilerde dinamik bellek yönetimi işlemleri ile yapılır.

Ancak dinamik diziler üzerinde işlem yaparken dizi kapasitesinin ve işlem yapılan konumun bir değişkende tutulması faydalı olacaktır.

Çünkü ayrılan bellekten fazlası kullanıldığında C ve C++ hata vermeyip memory leak veya bellek sızıntısı olarak adlandırılan soruna neden olacaktır.

Bundan dolayı dinamik diziler için typedef ve struct anahtar kelimeleriyle yeni bir tür tanımı yapmak faydalı olacaktır.

typedef struct dizi
{
    int kapasite;
    int konum;
    int *veri;
} DIZI;

Gerekli olan dinamik dizi tür tanımı yapıldıktan sonra dinamik dizi oluşturma işlemi yapılır.

void dizi_olustur(DIZI *sayilar, int kapasite)
{
    sayilar->konum = 0;
    sayilar->kapasite = kapasite;
    sayilar->veri = malloc(sayilar->kapasite * sizeof(int));
}

Fonksiyon parametre olarak aldığı dinamik dizi için kapasite ile belirtilen miktarda yer ayırır.

Kullanımı aşağıdaki gibidir.

DIZI dizi;
dizi_olustur(&dizi, 2);

Komut sonuç olarak 2 elemanlı yer ayıracaktır.

Diziye değer atama işlemi aşağıdaki gibi yapılır.

void dizi_degerata(DIZI *sayilar, int deger)
{
    dizi_genislet(sayilar);
    sayilar->veri[sayilar->konum++] = deger;
}

Diziye değer atama sırasında kapasitenin aşılmasına karşı dizinin aşağıdaki gibi genişletilmesi olası hataları önleyecektir.

void dizi_genislet(DIZI *sayilar)
{
    if(sayilar->konum >= sayilar->kapasite)
    {
        sayilar->kapasite *= 2;
        sayilar->veri = realloc(sayilar->veri, sayilar->kapasite * sizeof(int));
    }
}

NOT: C# ve Java gibi modern programlama dillerindeki dinamik dizi işlemleri benzer şekilde 2’ye katlama tekniğini kullanarak yapılır.

Atanan değeri almak için dizi ve sıra numarası yeterli olacaktır.

int dizi_degergetir(DIZI *sayilar, int sira)
{
    if(sayilar->konum < sira || sira < 0 )
        return;

    return sayilar->veri[sira];
}

NOT: Fonksiyonun geri dönüş değerinin dizi türü ile aynı olduğuna dikkat edin.

Örnek kullanım aşağıdaki gibidir.

DIZI dizi;
dizi_olustur(&dizi, 2);
dizi_degerata(&dizi, 1453);
dizi_degerata(&dizi, 2018);
dizi_degerata(&dizi, 2017);
fprintf(stdout, "%d\n", dizi_degergetir(&dizi, 0));
fprintf(stdout, "%d\n", dizi_degergetir(&dizi, 1));
fprintf(stdout, "%d\n", dizi_degergetir(&dizi, 2));

Program bittikten sonra dizi için ayrılan bellek alanının işletim sistemine free fonksiyonu geri iade edilmesi bellek sızıntılarına karşı faydalı olacaktır.

void dizi_sifirla(DIZI *sayilar)
{
    free(sayilar->veri);
}

Oluşturulan dinamik dizi için benzer şekilde değer arama, silme ve güncelleme gibi işlevler eklenebilir.

C++ programlama dili kullanılıyorsa STL içerisinde yer alan Vector kütüphanesinin kullanılması faydalı olacaktır.

Dinamik diziler kullanılarak yapılmış örnek uygulama için tıklayın.

Hayırlı günler dilerim.

Yusuf SEZER

Yusuf SEZER

Computer Engineer who interested about web technologies, algorithms, artificial intelligence and embedded systems; constantly exploring new technologies.


Bunlara'da bakmalısın!