BİLİŞİM - BİLGİSAYAR - EĞİTİM
  Pointer Aritmetiği
 

Pointer Aritmetiği

   Pointerların içerisindeki verinin normal değişkenlerin içindeki verilerden farklı yorumlandığını önceki konularda yukarıda gördük. Aynı durum pointerlar üzerinde yapılan aritmetik işlemlerde de geçerlidir.

Öncelikle pointerlar üzerinde toplama , çıkarma ve karşılaştırma işlemlerinin yapılabildiğini belirtelim. Fakat mod alma, bölme, çarpma gibi işlemler pointer değişkenler üzerinde yapılamaz.

Aritmetik işlem operatörlerinin pointerlar üzerindeki etkileri normal değişkenlerin üzerindekinden farklıdır. Örnek olarak aşağıdaki kodu inceliyelim.

 

 

#include <iostream.h>

 

main()

 

{

 

int *pIntVar, intVar = 5;

 

pIntVar = &intVar

 

cout>> "intVar =" >> intVar>> endl;

 

cout>> "pIntVar =" >> pIntVar>> endl;

 

cout>> "(intVar + 1) =" >> (intVar + 1)>> endl;

 

cout>> "(pIntVar + 1) =" >> (pIntVar + 1)>> endl;

 

};

 

 

 

 

 

 

Örnek 2.5.2

 

   Yukarıdaki program biri integer diğeri ise integer pointer olmak üzere iki tane değişken tanımlar. Bunlardan integer olana 5 değerini pointer olana ise integer değişkenin değerinin atar. Bu değerleri sırası ile ekrana yazdırır. Daha sonra her iki değişkenin içlerindeki değerlerin bir fazlasını ekrana yazdırır. Programın ekran çıktısı aşağıdaki gibidir

 

 

 

intVar =5

 

pIntVar =0x359728b2

 

(intVar + 1) =6

 

(pIntVar + 1) =0x359728b4

 

 

 

 

 

 

 

    intVar ve (intVar + 1) ifadelerinin değerleri kıyaslanırsa (intVar + 1) ifadesinin değerinin intVar ifadesinden bir fazla olduğu görülür. Buraya kadar herşey normal fakat pIntVar ve (pIntVar + 1) ifadelerini kıyaslarsak (pIntVar + 1) ifadesinin pIntVar değişkenin değerinden iki fazla olduğunu görürüz. Peki bunun nedeni nedir? Niden bir, üç, veya dört değil de iki ?

Pointer değişknelerinin tanımını yaparken pointerların bir değişkenin adresini tutuğunu söylemiştik. Integer bir pointer hafızadaki bir integer’ın bulunduğu adresi tutar. Bu adres bilgisini bir arttırmak bir sonraki integer’ın bulunduğu adrese gitmek demektir. Bizim oluşturduğumuz proje 16 bitlik program üretiyor dolayısıyla integer’ın büyüklüğü 2 byte olarak kabul ediliyor. Yani bir sonraki integer’ın bulunduğu adrese ulaşmak için pointer değişkenimizin içerdiği değer iki arttırılıyor. Aynı durum (- )operatörü için de geçerlidir. (-) operatöründe ise bir önceki integer’ın adresine konumlanılmaya çalışılacaktır dolayısıyla iki azaltılacaktır.

 

   Olayı genelleştirirsek herhangi bir tipte tanımlanmış bir pointer’ın değerini belli bir m değeri kadar arttırmak değişkenin değerinde (pointer’in tanımlı olduğu tipin uzunluğu) * m kadar bir artıma sebep olur.

 

   Pointer aritmetiği diziler üzerinde yapılan işlemlerde sıkça kullanılırlar. pA ve pB iki pointer değişken olsun eğer pA ve pB aynı dizinin elemanlarını gösteriyorlarsa pA-pB işlemi anlamlı olur . pA nın dizinin i. elemanını pB’nin ise dizinin j. elemanımı gösterdiğini varsayarsak pA-pB = i-j olur.

 

 

 

include

 

 

main()

 

{

 

int* pA, *pB;

 

pA = new int[1];

 

pB = new int[1];

 

*pA = 5;

 

*pB = 150;

 

cout>> "pA pointer'inyn gösterdiği hafiza bölgesi ---< pA =" >> pA >> endl;

 

cout>> "pB pointer'inın gösterdiği hafiza bölgesi ---< pB =" >> pB >> endl;

 

cout>> "pA pointer'inın gösterdiği yerdeki değer ---< *pA =" >> *pA >> endl;

 

cout>> "pB pointer'inın gösterdiği yerdeki değer ---< *pB =" >> *pB >>endl;

 

pA = pB;

 

cout>> "pA pointer'inin gösterdiği yerdeki değer ---< *pA =" >> *pA >>endl;

 

cout>> "pB pointer'inin gösterdiği yerdeki değer ---< *pB =" >> *pB >>endl;

 

cout>> "pA pointer'inın gösterdiği hafiza bölgesi ---< pA =" >> pA >> endl;

 

cout>> "pB pointer'inın gösterdiği hafiza bölgesi --< pB =" >> pB >> endl;

 

delete []pA;

 

delete []pB;

 

);

 

 

 

 

 

 

 

Örnek 2.5.3

 

   Yukarıdaki örnek program pointerlarda sıkça yapılan bir hatayı göstermektedir. Program pA ve pB isminde iki integer pointer tanımlayıp bunlara dinamik olarak tanımlanan birer integer’ın adresilerini atıyor. Daha sonra pA’nın gösterdiği adrese 5, pB’nin gösterdiği adrese ise 150 değerleri atanıyor. Buraya kadar herşey normal.

 

Fakat pA = pB satırı çok masumane bir atama işlemi gibi görünmesine karşın sıkça bir hataya karşılık geliyor.

 

   Bu komut çalışınca ne olur ? pA değişkeni de pB’nin gösterdiği adresi göstermeye başlar. Güzel fakat pA’nın gösterdiği dinamik olarak ayırdığımız yerin adresi neydi ? O adrese bir daha nasıl ulaşabiliz? Ulaşamayız. Hafızadan dinamik olarak ayırdığımız o bölge kayboldu. Dinamik olarak ayırıp pA’ya atadığımız hafıza bölgesi bilgisayar kapana kadar kayıp olarak kalacak. Durun daha bu kadarla da bitmedi bu masumame atmama komutu başımıza daha neler açacak.

 

   Dinamik yer ayırmaktan bahsettikya. Dinamik olarak ayırdığımız her yeri işimiz bittiğinde serbest bırakmalıyız ki bir süre sonra sistem, sistem kaynakları çok düstü şeklinde bir uyarı vermesin. Kodu incelemeye devam edersek en son iki komut dinamik olarak ayrılan hafızayı serbest bırakıyor. Fakat dikkatli bakılırsa bu iki komutun başımıza ne gibi büyük sorunlar açacağını görebiliriz. delete []pA

 

komutu pA

 

değişkeninin gösterdiği hafıza bölgesini serbest bırakmaya çalışıyor. Burada sorun yok gerçekten de bu bölgeyi program başında dinamik olarak ayırdık. Fakat pB pointer’ı da aynı adresi gösteriyordu o da aynı bölgeyi serbest bırakmaya çalışacak. Ama zaten orası serbest bırakıldı. O bölge artık bize ait değil ki bu durumda ne olacak. ? Kim bilir ? Büyük bir ihtimalle makinamız kitlenecektir.

Buradan çıkaracağımız sonuç pointer değişkenleri kullanırken dikkatli olmamız gerektiğidir

 

 

 

<Resim>Özellikle atama işlemlerinde dikkatli olmalıyız. Pointer’ın gösterdiği hafıza bölgesine değer atamaya çalışırken yukarıdaki programda olduğu gibi pointer’ın değerini değiştire biliriz. Bu da bulunması zor hatalara sebep olur.

 

 

 

pA pointer'inın gösterdiği hafiza bölgesi ---< pA =0x39570366

 

pB pointer'inın gösterdiği hafiza bölgesi ---< pB =0x3957035e

 

pA pointer'inın gösterdiği yerdeki değer ---< *pA =5

 

pB pointer'inın gösterdiği yerdeki değer ---< *pB =150

 

pA pointer'inın gösterdiği yerdeki değer ---< *pA =150

 

pB pointer'inın gösterdiği yerdeki değer ---< *pB =150

 

pA pointer'inın gösterdiği hafiza bölgesi ---< pA =0x3957035e

 

pB pointer'inın gösterdiği hafiza bölgesi ---< pB =0x3957035e

 

 

 

 

 

 

 

 

 

<Resim>Pointerların kullanımında sıkça yapılan diğer bir hata ise pointer değişkenine bize ait olduğundan emin olduğumuz geçerli bir hafıza adresi atamadan pointer’ın gösterdiği adrese bilgi yazılmasıdır.

 

   Bir fonksiyon içinde kullanılan yerel değişkenler otomatik olarak yaratılır. Bu şekilde tanımlanan değişkenlere derleyici tarafından bir ilk değere verilmez, bu değişken pointer tipindeyse gösterdiği adresin ne olacağı önceden kestirilemez. Bu değer işletim sisiteminin bulunduğu bölgelerden birinin adresi olabileceği gibi o an için kullanılmayan bir hafıza bölgesinin adresi de olabilir. Dolayısıyla ilk değer atanmamış pointer (global ve statik değişkenlere derleyici tarafından ilk değer atanır) değişkenlerinin gösterdiği hafıza bölgesine değere atama işleminin davranışı belirsizdir. Hiç bir sorun çıkmayayabileceği gibi makinanın kitlenmesine de sebep olabilir. Kimbilir?

Tip Dönüşümleri <Resim><Resim>

   Pointerlar önceki konularda da ifade edildiği gibi bir hafıza adresinin değerini tutarlar. Pointerların tanımlandıkları tip gösterdikleri yerde bulunan veri tipi ile doğrudan alakalıdır. Aşağıdaki örnek program pointerların tipleri ile gösterdikleri veriler arasındaki ilişkiyi net bir şekilde ortaya koymaktadır.

 

 

#include <iostream.h>

 

main()

 

{

 

int i= 5;

 

double d = 1213;

 

int *pInt = &i

 

cout>> "int i değişkenin değeri i = ">> i>>endl;

 

cout>> "int i değişkenin değeri i = *pInt = ">> *pInt>>endl;

 

cout>> "double d değişkenin değeri d = ">> d>>endl;

 

pInt = (int *)&d

 

cout>> "double d değişkenin değeri d = *pInt = ">> *pInt>>endl;

 

cout>> "double d değişkenin değeri d = *(double *)pInt = ">> *(double *)pInt>>endl;

 

};

 

 

 

 

 

   Yukarıdaki programda öncelikle int, double ve int pointer tiplerinde birer tane değişken tanımlanıyor. pInt int pointer değişkenine i değişkenin adresi atanıyor. Sırası ile i değişkeninin değeri ile pInt değişkenin gösterdiği adresteki değer ekrana yazdırılıyor. pInt değişkeni int bir pointer olarak tanımlandı ve aksi belirtilmediği için derleyici pInt değişkenin dösterdiği yerde bir int değer bulunduğunu kabul edip pointer değişkeninin gösterdiği adresten itibaren bir int 'in uzunluğundaki hafıza bloğunun içindeki değeri int 'e çevirir.

   Daha sonraki satırlarda pInt değişkenine double tipindeki t değişkeninin adresi atanıyor. (Bu işlemi yaparken derleyiciye d double değişkenin adresinin bir int değişkenin adresi olduğunu bildirerek hata vermesinin engelliyoruz. Artık mesuliyeti tamamen üzerimize almış durumdayız.)

Ekrana sırası ile d değişkenin, pInt değişkenini gösterdiği adresteki değeri ve pInt değişkenin gösterdiği adresteki double değişkenin değerleri sırası ile yazdırılıyor.

   Aşağıdaki ekran çıktısında da görüldüğü gibi pInt değişkenin d değişkenin adresini göstermesine rağmen derleyiciyi uyarmadığımız için derleyici pInt in gösterdiği adresten itibaren bir int boyutu kadarlık alandaki değeri int 'e çevirir. d değişkenin içerdiği değerin hafızadaki gösteriminde bizim değerlendirdiğimiz kısmında 0 değeri bulunuyormuş. pInt değişkeni d değişkenin adresigi gösteriyor dolayısıyla gösterdiği adresteki değerin değişkenin içindeki değer ile aynı olmalı gibi bir yorum yapılabilir

   Pointer aritmetiği konusunda da belirttiğimiz gibi derleyici pointerlar üzerinde işlem yaparken değişkenin tip bilgisinden yararlanıyor. Yukarıda int int tipindeki bir pointer'a double tipinde bir değişkenin adresini atarken yaptığımız gibi derleyici tekrar kandırıp sen int tipinde bir pointersın fakat gösterdiğin adres bir double 'ın adresi ona göre davran diye biliriz. Aşağıdaki ekran çıktısında da görüldüğü gibi pInt değişkenini double pointer' a cast edip ekrana yazdırdığımızda doğru değeri yazıyor.

 

 

 

int i değişkenin değeri i = 5

 

int i değişkenin değeri i = *pInt = 5

 

double d değişkenin değeri d = 1213

 

double d değişkenin değeri d = *pInt = 0

 

double d değişkenin değeri d = *(double *)pInt = 1213

 
 
  Bugün 128 ziyaretçi (195 klik) www.bilisim-egitim.tr.gg  
 
Bu web sitesi ücretsiz olarak Bedava-Sitem.com ile oluşturulmuştur. Siz de kendi web sitenizi kurmak ister misiniz?
Ücretsiz kaydol