etasarim avatar

Dinamik Bellek Kullanımı – C Programlama Dili

etasarim

Published: 25 Mar 2019 › Updated: 25 Mar 2019Dinamik Bellek Kullanımı – C Programlama Dili

Dinamik Bellek Kullanımı – C Programlama Dili


C programlama dili serisinin bu bölümünde dinamik bellek kullanımına değineceğim. Pointer kavramı bu dersle beraber oldukça anlam kazanmış olacak. Hazırsanız başlayalım.

Önceki derslerimizde pointer ve diziler konusunu ayrıntılı bir şekilde ele almıştık. Bu dersimizle bu iki kavram arasındaki ilişkiyi nihayetlendireceğiz.

Pointerların dizilerden en büyük farkı dinamik hafıza kullanımına imkan veriyor olmasıdır.

Bir programda dizi kullanacaksak başlangıçta dizi boyutu bir sabitle verilmelidir. Dizi boyutu olarak program çalıştıktan sonra olabilecek bir değer veremeyiz. Örneğin,

int a = 10;
int d[a];

gibi bir tanımlama C99 standardına göre hatalıdır. Çünkü program çalıştıktan sonra a değişkeninin değeri belli olmaktadır ve d dizisinin boyutu program çalıştıktan sonra belli olacaktır.

Diziler için bellekte program çalışırken yer tahsis etmek mümkün olmasa da pointerlar ile bu yapılabilir.

alt

C dilinde dinamik bellek kullanımı için genellikle malloc() ve free() fonksiyonları beraber kullanılır.

malloc() yani memory location fonksiyonu(komutu), hafızada belirttiğimiz kadar yer ayırır ve ayrılan yerin adresini döndürür.

void * tipinde veri döndürdüğü için (tipsiz) bir pointera atamasını yaparken type casting işlemi yapmalıyız. Bunu da atama yapmadan önce fonksiyonun baş kısmına (int *) gibi bir ifade getirerek yaparız.

Böylelikle malloc() fonksiyonu ile bellekte yer tahsis edilirken free() fonksiyonu ile bu yer boşa çıkarılacaktır. Eğer ki tahsis edilmek istenen bellek ihtiyacı karşılayamıyorsa NULL bir işaretçi geri döner..

Bu iki fonksiyon “stdlib.h “ kütüphanesinde tanımlandığından bu fonksiyonları kullanırken bu header dosyasını kaynak kodumuza dahil etmemiz gerekir.

alt

malloc() fonksiyonu sayesinde pointerlarda önceden yapmış olduğumuz gibi bir değişkenin adresini atama gereksinimi ortadan kalkıyor. Bunun sebebi ise malloc() fonksiyonunun tahsis edilen belleğin adresini direk işaretçiye geri verebilmesindendir.

Yeri gelmişken şunu da belirtelim: Programımızın çalışması için bellekte ayrılan yer programımız sona erdiğinde boşa çıkacaktır.

Bu kadar açıklamadan sonra bu fonksiyonların kullanımını görebileceğimiz basit bir uygulama yapalım:

alt

Şimdi de program üzerine konuşalım.

Uygulamanın başında ipt adında int tipinde bir pointer tanımladık. Sonrasında malloc() fonksiyonu içerisinde sizeof() operatörünü kullanarak 6 integer lık bir yer ayırdık. Bu fonksiyon void * tipi döndürdüğü için (int *) ifadesi ile type casting işlemi yaptırdık, yani tipsiz pointer türünü int pointer türüne dönüştürmüş olduk.

Sonrasında bir for döngüsü içerisinde :

ipt[i] = i +1;

ifadesi ile pointerımızı sanki bir dizi gibi indis değeriyle kullanarak ilk değer atamalarını yaptık.

Sonrasında kullandığımız printf() fonksiyonları ise oldukça önemli.

alt

ipt[i] ifadesi adresteki değer bilgisini verirken ipt + i ifadesi ise adres değerini vermektedir.

*(ipt +i ) ile ipt[i] aynı anlama gelmektedir.

alt

Programın sonunda vermiş olduğumuz

free(ipt);

komutu ile bellekte tahsis edilen yer boşaltılır.

Uygulamamızın çıktısı ise aşağıdaki gibidir :

alt

Ufak bir hatırlatma :

Nasıl değişkenleri kullanmadan önce bir değer ataması yapmamız gerekiyorsa Pointerlar da birer değişken olduğundan onlar için de bu durum aynen geçerli. Biz bu uygulamamızda önceki uygulamalarımızdan farklı bu atamayı malloc() fonksiyonu ile yapmış olduk.

malloc() fonksiyonunu anlatırken eğer yer tahsis etme işlemi başarılı değilse NULL döndürdüğünden bahsetmiştik.

Bu kontrolü nasıl yapacağımızı bir karakter dizisi üzerinde görelim:

alt

Uygulamamızın başında char tipinde adı cpt olan bir pointer tanımladık. Sonrasında malloc() fonksiyonunu kullanarak 20 karakterlik yer tahsis edip başlangıç adresini cpt pointerına atadık.

Sonrasında gelen if sorgusunda ise bu atamanın başarılı olup olmadığı sorgulanmaktadır. Eğer atama başarılı değilse NULL yani 0 değeri döndüreceğinden tersini aldığımızda değeri 1 olacaktır ve if sorgusunun içine girecektir. printf() fonksiyonu ile kullanıcıya hata mesajı verildikten sonra exit() fonksiyonu ile uygulamadan çıkılacaktır.

Eğer atama işlemi başarılı ise if sorgusuna girilmeyecek ve sonrasındaki kodlar işlenecektir. printf() fonksiyonu ile kullanıcıya metin girmesi için mesaj verilecek, gets() fonksiyonu ile girilen metin cpt pointerı için ayrılan yere atanacaktır.

Programın sonundaki  free() fonksiyonu ile cpt için ayrılan yer boşa çıkarılacaktır.

alt

Şimdi de pointer ve dizi kavramını zihnimizde netleştirecek güzellikte bir örnek yapalım:

alt

Uygulamamızın başında 3 adet char tipinde pointer tanımladık : cpt1, cpt2 ve cpt3.

Bunlardan cpt3’ü bildirimini yaparken ilk değer atamasını da aşağıdaki kod ile yaptık :

char *cpt3 = "Bu 3. karakter dizisidir";

Sonrasında  40 elemanlı adı cdizi olan bir karakter dizisi tanımladık:

char cdizi[40];

Görüldüğü gibi bu dizinin bildirimini yaparken ilk değer atamasını yapmadık. Sonrasında  aşağıdaki gibi bir ilk değer ataması yaparsak,

cdizi = "Bu dizi olan karakter dizisidir";

Uygulamamızda hata alırız. Çünkü C dilinde karakter dizisi bildirimi yaparken ilk değer ataması yapmamız gerekir aşağıdaki gibi :

char cdizi[40] ="Bu dizi olan karakter dizisidir";

böyle bir tanımlamayla hiçbir hata almayacaktık. Peki bir karakter dizisi bildirimi esnasında ilk değer ataması yapmamışsak sonrasında değer atayamaz mıyız?

Böyle bir durumda değer atamak için strcpy() fonksiyonunu kullanmak gerekir. Aşağıdaki kod ile bu mümkündür :

strcpy(cdizi, "Bu dizi olan karakter dizisidir");

Karakter dizilerindeki bu ilk değer atama sorunu normal diziler için geçerlidir. Pointerlar da böyle bir sorun yoktur. Bunu aşağıdaki koddan anlayabiliriz :

cpt1 = "Bu 1.karakter dizisidir";

Çıktımız aşağıdaki gibidir :

alt

Uygulamanın diğer kodları rahat anlaşılıyor diye açıklama yapmıyorum. Bu dediklerimiz karakter dizisi için geçerlidir.

Normal bir int dizi tanımladıktan sonra değer atamasını sonradan yapabiliriz. Aşağıdaki bir kod hata vermeden çalışacaktır:

int dizi[5];

dizi[1] = 100;

Son olarak bir char pointer'a değer atamadan önce onun için bellekte yer ayırmamız gerekir, eğer yer ayırmazsak aşağıdaki kodun 2.satırı hatalı olacaktır :

cpt2 = (char)malloc(sizeof(char)30);
strcpy(cpt2, "Bu 2.karakter dizisidir"); // ***

alt

Dersimizi sonlandırmadan önce calloc() fonksiyonundan da bahsetmek istiyorum. Bu fonksiyon da bellekte yer ayırmak için kullanılır anca malloc() fonksiyonundan farklı olarak 2 ayrı parametre alır : eleman boyutu ve eleman sayısı

Karşılaştırabilmek adına şu kodlara bakalım :

int *ipt ;

ipt = malloc(sizeof(int)*10);

ya da

ipt = calloc(10, sizeof(int));

görüldüğü gibi çok da bir fark yok. Sadece kullanımını görelim istedim.

Bugünlük bu kadar, umarım faydalı bir çalışma olmuştur.

Uygulama noktasında herhangi bir sorun yaşarsanız aşağıdaki yorum panelini kullanarak iletişime geçmekten çekinmeyin lütfen. Teşekkürler.

alt

Kaynak belirtilmeyen görseller etasarim@etasarim a aittir. / Pictures that don’t have any source belongs to etasarim@etasarim.



Posted from my blog with SteemPress : http://etasarim.cloudaccess.host/25/03/2019/dinamik-bellek-kullanimi-c-programlama-dili/

Leave Dinamik Bellek Kullanımı – C Programlama Dili to:

Written by

Ekip hesabıdır. | We are a designer group. (Adobe Photoshop, Adobe Illustrator), and photographer

Read more #tr posts


Best Posts From etasarim

We have not curated any of etasarim's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From etasarim