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.

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.

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:

Ş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.

ipt[i] ifadesi adresteki değer bilgisini verirken ipt + i ifadesi ise adres değerini vermektedir.
*(ipt +i ) ile ipt[i] aynı anlama gelmektedir.

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 :

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:

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.

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

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 :

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"); // ***

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.

Kaynak belirtilmeyen görseller @etasarim a aittir. / Pictures that don’t have any source belongs to @etasarim.
Posted from my blog with SteemPress : http://etasarim.cloudaccess.host/25/03/2019/dinamik-bellek-kullanimi-c-programlama-dili/
Uygulamalarda ne kadar girdinin belli olmayacağı zamanlar için can kurtaran bir durumdur : dinamik bellek kullanımı. Zor olmamakla birlikte bilinmesi gereken önemli konulardandır.
You got a 1.55% upvote from @minnowvotes courtesy of @etasarim!
Hi, @etasarim!
You just got a 1.74% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.
Bu yazı Curation Collective Discord Sunucusunda küratörlere önerilmiş ve manuel inceleme sonrasında @c-squared topluluk hesabından oy ve resteem almıştır.
This post was shared in the #turkish-curation channel in the Curation Collective Discord community for curators, and upvoted and resteemed by the @c-squared community account after manual review.
@c-squared runs a community witness. Please consider using one of your witness votes on us here
Thanks for support
Congratulations! This post has been upvoted from the communal account, @minnowsupport, by etasarim from the Minnow Support Project. It's a witness project run by aggroed, ausbitbank, teamsteem, someguy123, neoxian, followbtcnews, and netuoso. The goal is to help Steemit grow by supporting Minnows. Please find us at the Peace, Abundance, and Liberty Network (PALnet) Discord Channel. It's a completely public and open space to all members of the Steemit community who voluntarily choose to be there.
If you would like to delegate to the Minnow Support Project you can do so by clicking on the following links: 50SP, 100SP, 250SP, 500SP, 1000SP, 5000SP.
Be sure to leave at least 50SP undelegated on your account.