WeWereRock
C Pointers konusundan sonra şimdi biraz daha derinlere inelim. Bakalım pointer’a dair daha
başka neler var
Bilindiği üzere C dilinde int, double ,char vb. tiplerde bir pointer oluşturabiliyorduk ve bu pointerlar vasıtası ile adresler üzerinde istediğimiz işlemleri yapabiliyorduk. Fakat biz şunu
biliyoruz ki adresler üzerinde yapılan işlemler diğer sıradan işlemlere göre biraz daha bilgi isteyen ve biraz daha riskli işlemlerdir. Bu nedenle bu makalenin ağırlığı daha çok bu konu üzerine olacak.
C dilinde adresleme konusunu ikiye ayırabiliriz.
1 ) static adresleme ( array, const ... )
2 ) dynamic adresleme ( pointer )
Bunun en güzel örneği array ile pointer arasındaki farktır. Bir array’in boyutu program başlamadan verilir ve program sonuna kadar değiştirilemez.
Örneğin;
int arr[10]; şeklinde boyutu 10 olan bir integer array tanımladık fakat işlemlerimiz ilerleyince anladık ki bize 11 tane eleman lazım. Peki biz
int arr[11] = 7
şeklinde bir atama yapabilir miyiz ? C dili böyle bir atamaya izin vermez. Bize ait olmayan bir alana erişemeyiz. Bu bir segmentation fault’dur ve compile time’da karşımıza çıkar. İşte pointer farkı burada işimize yarıyor
Malloc & Free
Malloc aldığı parametre kadarlık alanı allocate eden bir fonksiyondur ve pointer’a yer almada kullanılır. Free ise aldığımız alanı işletim sistemine geri vermek için kullandığımız bir başka fonksiyondur. Hemen bir örnekle işin esprisini çözelim.
Görüldüğü üzere boyutu 10 olan bir integer pointer’ının boyutunu 11 yaptık. İşte pointerın en güzel yanı bu, yani dinamik programlama. İstediğimiz an alanı genişletip, istediğimiz an alanı daraltabiliriz. Hafızayı deallocate ederken de free fonksiyonunu kullandık. İşin tehlikeli yanı burası. Eğer büyük bir program yazıyorsak ve aldığımız alanları geri vermediysek
bir süre sonra run-time’da stack overflow hatası alabiliriz ki bu hata bir programcının logic hatalar ile birlikte en çok korktuğu hataların başında gelir.
MALLOC ve FREE hakkında daha geniş bilgi için :
malloc - C++ Reference
free - C++ Reference
VOID POINTER
Fundamental ( temel ) tiplerde pointer’ları görmüştük. Bir integer pointer’ına integer değerler, bir char pointer’ına char değerleri atayabiliyoduk. İyi ama void türünde bir pointer’a biz ne atıyacağız ?
Void pointer, üzerinde herhangi bir aritmetik işlem yapamadığımız ve indexleyemediğimiz, sadece casting işlemlerini gerçekleştirmek için kullanılan pointer türüdür.
Bir float pointer üzerinde yürüyebiliyorduk veya bu pointer’ı başka bir float pointer ile kıyaslayabiliyorduk. Bu işlemleri void pointer üzerinde yapamayız fakat void pointer’ın öyle bir artısı var ki coder’ları çok büyük zahmetlerden kurtarıp, dilin esnekliğini artırıyor. Bir
void pointer’ına tipi ne olursa istediğimiz başka bir pointer’ı atayabiliriz. Peki bu bize ne sağlar bir örnek üzerinde inceleyelim.
void * bsearch ( const void * key, const void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) ); [\\\\FONT]
Yukarıdaki prototype çok bilindik bir fonksiyon olan binary search fonksiyonunun prototype’dır. Prototype’da da görüldüğü üzere bu fonksiyon const void pointer’lar
alıyor fakat bizim bütün fundamental tiplerimiz üzerinde çalışıyor.
Örneğin;
Görüldüğü gibi bir tane comparator function sayesinde istediğimiz tipi bsearch fonksiyonu sayesinde sıralayabiliyoruz. Bu fonksiyon belki 30 belki 40 sene önce yazıldı ama hala işimizi
görebiliyor. İşte bu void pointer’ın artısı
BINARY SEARCH hakkında daha geniş bilgi için :
bsearch - C++ Reference
CASTING
Binary search fonksiyonunu kullanırken ekstradan bir compare fonksiyonu yazdık ve içerisinde iki pointer arasındaki farkı return ettik. Fonksiyona gelen değerler
const void pointer ve biz dedik ki void pointer’lar üzerinde işlem yapamıyoruz. Peki biz bunların arasındaki farkı nasıl aldık ozaman ?
Casting, farklı tiplerdeki iki değişkeni birbirine atamak için kullanılan metottur.
Örneğin;
Yukarıdaki kodda görüldüğü gibi integer olan değeri double türündeki bir değere cast ettik ve ekrana bastırdık. Aynı void pointer’ın integer’a veya double’a cast edildiği gibi. Bu kadar kolay ( Eğer biz burada integer’ı cast etmeyip double’a direk atasaydık da bu işlemin sonucu değişmeyecekti, çünkü fundamental tiplerin birbirine atanması olayı compiler tarafından otomatik cast ediliyor. C ’de cast işlemleri compareints ve comparedoubles fonksiyonlarında olduğu gibi ağırlıklı olarak pointer’lar üzerinde kullanılır. )
FONKSİYON POINTER
Dikkat ettiyseniz binary search fonksiyonunun prototype’ında farklı bir parametre vardı.
int ( * comparator ) ( const void *, const void * )[\\\\FONT]
İşte bu bir fonksiyon pointer’ıdır. Bir fonksiyon pointer’ı yazmanın bildiğimiz fonksiyon yazmadan hiçbir farkı yoktur. Tek fark onu kendisine parametre olarak alacak fonksiyon prototype’ndadır. Bunun örneğini de binary search prototype’ında görmüştük. Binary search örneğini hatırlarsak eğer hem double hem de integer için çalışmıştı. Çünkü biz orada bir fonksiyon pointer’ı kullandık. Eğer sıralamak istediğimiz tip integer ise compareints, double ise comparedoubles fonksiyon pointer’ını çağırdık. Fonksiyon pointer’ı dediğimiz şey bu işe yarar. Kendisi bir pointer olduğu için başka fonksiyonlara parametreymiş gibi yollayabiliriz.
Hatalı olduğum yerler olabilir, görenlerin bildirmesi rica olunur
Soru soracak olursanız bu başlık altından sorabilirsiniz.
İyi çalışmalar ...