İşaretçiler namı diğer “Pointer”

Bu yazımızda işaretçilerden bahsedeceğim.                       İşaretçi= Adres tutucu=Pointer;

       İşaretçiler bellekten aldığınız yerin adresini tutmada kullanılır. Bir işaretçiyi “ int *pIsaretciAdi; ” şeklinde kodlayarak oluştururuz. İşaretçilerin başlarına p harfini koyarız ki onun işaretçi olduğunu unutmayalım. Sizde bunu standart haline getirseniz iyi olur.

işaretçi

  1. Şekilde görüldüğü üzere ilk verilen tip pointerin değil tutulmak istenen tipi işaret eder bu tip: char, int, double… olabilir. Fakat pointerin tipi herzaman “int” dir
  2. Yıldız sayısı arttıkça pointerin derecesi artar. Peki  ya bu ne demek? Yeni başladıysanız sizin için önemli değil fakat pointerıda bir pointerda tutma ihtiyacı hissediyorsanız burada yıldısayısı arttıyor. (bir dahaki yazımda bu konuyu anlatacağım)
  3. işaretçiye vermek istediğiniz ism başına p koymak ide’lerde işaretçileri ayırt etmenizi sağlar.

İşaretçiler bellekten aldığınız yerin adresini tutmak için c/c++ dilinde vardırlar.
Stack (dinamik olmayan) hafızada oluşturduğumuz değişkenlerin adresleri değişken adında tutulduğu için zaten bellidir o yüzden tekrar bir işaretçiye genelde ihtiyaç duyulmaz. Fakat kullanmakta mümkündür.

Örnek verecek olursak

[code language=”cpp”]
int a;  // dediğimizde stackden yer almış oluruz ve
//bunun adresini zaten “a” değişkeni tutuyordur.
int* pA=&a;  // şeklinde a’nın adresini yinede tutabiliriz.
[/code]

Fakat dikkat edilmesi gereken bazı hususlar vardır. Bir stack verisi kod bloğu bittiğinde silinir.

Yani

[code language=”cpp”]
{
int a=5;
int* pA=&a;
return pA;
}
[/code]

Diyerek döndürdüğünüz pointerın (pA)  tuttuğu adrese erişmek istediğinizde kod bloğu bitmiş olan a değişkeninin yeri boşaltılmış (serbest bırakılmış) olacağından hatalı erişim sağlamış olacaksınız, sadece hatalı olsa iyi belki o hücreye başka programlar tarafından farklı değerler yazılmış olma ihtimali ile karşılaşacak, yanlış değerle işlem yapacaksınız yada başka programın kullandığı hücreyi kullanarak diğer programaın akışını bozacaksınız.

Bu durumu gidermek istersek pA pointerının tuttuğu adresi (yeri) de heapten almalıyız.

[code language=”cpp”]
{
int* pA= new int;
*pA=5;
return pA;
}
[/code]

Bu ise yukarıda görüldüğü gibi “ int * pA= new int; “ şeklinde alınır.

Burada yapılacak en büyük hata tek int’lik yer alınmasına rağmen

[code language=”cpp”]
*(pA+1)=25; /*veya*/ cout<<pA[2]; // ikiside hatalı
[/code]

Sıfırıncı hücre dışındaki hücrelere erişimin sağlanmasıdır. Bu tamamen sizin kontrol etmeniz gereken bir durumdur.(genelde bu hata döngülerde programcının gözünden kaçar)

Şu unutulmamalı ki her pointer bir adres tutar. Ve işaretçinin adı yazıldığında tuttuğu adrese, başına “*” koyduğunuzda adresteki değere, başına “&” koyduğunuzda ise işaretçinin adresine ulaşırsınız.
Adsız

İşaretçiye ihtiyaç stack (dinamik) hafızadan alınan verilerin adreslerinin sadece bir seferliğine yani alınırken erişilir olmasından kaynaklanır.

[code language=”cpp”]
new int[2];
[/code]

Yazılması durumunda hafızadan 2 integerlik yer alınacak new fonksiyonu tarafından dizinin ilk adresi döndürülecektir fakat siz bu adresi tutmazsanız size ait olan yere tekrardan ulaşamazsınız.
İşte bu dönen adresleri tutmak için oluşturulmuş tipler pointerlardır.

[code language=”cpp”]
int* pA= new int[2]; // 2 integer kadar yer alındı ve
//dönen adres pA pointerına atandı.
*pA=5; // ilk adreste bulunan yere 5 atandı.
pA[1]=7; // ikinci adreste bulunan yere 7 atandı
[/code]

Burada atama işleminde pointer iki şekilde kullanılmıştır.
a) “*pA” pA bir adres tutucusuydu, önüne yıldız (*) konulduğunda o adresteki veriye erişim sağlanmış olur.
a. Diğer hücrelere erişmek için ise *pA, *(pA+1), *(pA+2), *(pA+3)… şeklinde kodlanır.
b. Buradaki “pA+1” toplanan sayı yani +1 diğer değişkene geçmek demekti. Değişkenin türü int ise ,integer 4 baytdir, (pA’nın tuttuğu adres+4) anlamına gelir.
1
b) “pA[1]” Adres tutan pA pointerina indis verilince derleyici içine erişilmek istediğini anlıyor ve [ ] indisin içindeki değer ne ise o indisin ifade ettiği hücreye işlem yapmaya başlıyor.
a. Diğer hücrelere erişmek için pA[0], pA[1], pA[2], pA[3]… gibi kullanılabilir. Resimde görmek için tıklayınız.

Küçük bir program üzerinden anlatmaya devam edelim. Bu program aşağıda yazılan işleri sırası ile yapacaktır:
1. Stackden bir pointer yeri alacak
2. Sonra o pointer’a heapten aldığımız 5 int’lık yerin ilk adresini tutacak
3. Bu 5 elemanlı dizinin 5 elamanına (indisi^4) atanacak (ilk for)
4. Ve sonra Değer ler tek tek bastırılacak. (ikinci for)

Pointer-Örnek:

[code language=”cpp”]
#include<iostream>

using namespace std;

int main ()
{
int* pIsaretci= new int [5];

for (int i = 0; i < 5 ; i++)
{
*(pIsaretci+i)=i*i*i*i; // i^4= i*i*i*i;
}

for (int i = 0; i < 5; i++)
{
cout<<"Deger "<<i<<"= "<< pIsaretci[i]<<endl;
}
return 0;
}
[/code]

2
Resim: Program ekran çıktısı
Uygulamada işaretçi ile olan iki erişim yöntemini de kullandık.
1. *(pIsaretci+i)
2. pIsaretci[i]
Tek dereceli işaretçilerde kapalı parantezli yöntem daha anlaşılır ve kullanışlı oluyor.

Tüm içerik Abdullah Salih BAYRAKTAR tarafından hazırlanmıştır.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir