Papatyam Forum - Tekil Mesaj gösterimi - C Dökümanları
Konu Başlıkları: C Dökümanları
Tekil Mesaj gösterimi
Alt 20 January 2009, 15:50   Mesaj No:5

CoNQueRoR_61

Papatyam Usta Üyesi
Avatar Otomotik
Durumu:CoNQueRoR_61 isimli Üye şimdilik offline konumundadır
Papatyam No : 1397
Üyelik T.: 20 January 2009
Arkadaşları:0
Cinsiyet:
Memleket:istanbul
Yaş:35
Mesaj: 131
Konular:
Beğenildi:
Beğendi:
Takdirleri:10
Takdir Et:
Konu Bu  Üyemize Aittir!
Standart Ynt: C Dökümanları

Temel C Dokümanları 6 (Pointerlar[işaretçiler])

Sıra geldi pointerlara, C de ki en onemli konuya… Bu pointerları
da iyice oğrenirsek artık C de onumuz acık demektir.Peki nedir bu
pointer denen şey ?
Türkçe anlamı işaretçi demektir. Yani bunlar bir şeyleri işaret ederler.
Ama pointerların esas olayı RAMdeki byte'ların adreslerini tutan
değişkenler olmalarıdır. Yani pointerlar da integer, double yada
char gibi bir değişken turudur fakat sadece memory adresi tutarlar
ve diğer degisken turlerinden farklı olarak baska bir degiskeni
isaret edebilirler.Peki memory adresi dediğimiz şey nedir ve
işaret etmekden kastımız ne ? Diye soranların sesini duyar gibiyim
İlk önce RAMi inceleyelim biraz. RAM bilgisayarın işlemlerini
yurutebilmesi icin bazı bilgileri geçici olarak kaydettigi bir cesit
hard disktir. RAM byte'lardan oluşur mesela benim RAM im 256 mega byte.
bu da (1MB = 1024 Kilo byte ve 1Kb = 1024 byte dersek) 268435456 byte oluyor sanırım. RAM adresi bu bytelarla belirleniyor. 100000 diye

bir RAM adresi, RAM deki 100000 inci byte demek oluyor. Bu byte

dedigimiz şey de bit lerden oluşuyor.8 tane bit ten oluşan bir bloka

byte demişler. bit dediğimiz şey de bilgisayar dunyasındaki o meşhur 0 ve 1

lerin kaydedildigi yerlerdir. Yani bir bit de sadece doğru yada yanlış

bilgisi tutulabilir yani 0 yada 1 ... demek ki bir byte 8 tane 0 yada 1

den olusuyor ornek:



00001101 bir byte dir...



Bu 0 ve 1 lerin bilgisayarımıza taktığımız ve RAM dedigimiz o kartuşlarda

nasıl olustugunu merak ediyorsanız onuda soliyim. RAM in icindeki binlerce

kucuk elektronik switch lerle olusuyor. Bu switch ler acık yada kapalı

hale getirilerek 0 yada 1 i temsil ediyorlar. Elektronik dilinde bu switchlerin acık yada kapalı olmasını temsil eden şey de aletteki pinlerin ucunda voltaj olması ya da olmamasıdır. Bunu da bir ek bilgi olarak soylemiş olalım



RAM i şu şekilde hayal edelim:



.

.

.

00110010 ----> 124561 inci byte

01110011 ----> 124562 inci byte

10110010 ----> 124563 inci byte

00001011 ----> 124564 inci byte

00011101 ----> 124565 inci byte

10010011 ----> 124566 inci byte

00001111 ----> 124567 inci byte

00100101 ----> 124568 inci byte

.

.

.





124561 inci byte RAM deki adres oluyor. karşısındaki 0 ve 1 ler de o

adreste bulunan byte daki bilgilerdir.



biz yazdıgımız programda



int x;

x=5;



yazdıgımızda x değişkeninde bir bilgi tutulabilmesi icin RAM de bir adres

ayrılır ve o adrese 0 ve 1 ler kullanılarak x=5 bilgisi kaydedilir.

Bu kadar genel bilgiden sonra pointer tanıtma ve kullanmayı kodlarla

anlatalım artık...



pointerlar işaret edecekleri degiskenin turune gore tanıtılırlar

bir integer a pointer atamak istiyorsak pointerımızı şu şekilde belirleyecez:



int *p;



normal integer tanıtır gibi.. fakat tanıtacagımız degiskenin basına bir * işareti

koyunca o degişken pointer oluyor. Yukardaki komuttan sonra artık bir pointer

degişkenimiz var. Unutulmaması gereken bir nokta da pointerın da bir degişken oldugudur.

Simdi bu pointerla neler yapabilecegimize ve nasıl kullanıldıgına bakalım.



int *p;

int x;

x=5;

p=&x;



yukardaki kodlarla once bir integer pointerı belirledik. Sonra x adında bir

integer değişkeni belirledik ve ardından bu degiskenin degerini 5 yaptık.

Son satırda da pointerın x e işaret etmesini sağladık. Bunu & sembolu ile yaptık.

& işareti şu anlama geliyor: " ...nın adresi" yani &x, "x in adresi" anlamına geliyor.

Son satırdan sonra p nin degeri x in memory adresine eşitlendi. Mesela x degiskeninin

tasıdıgı degeri aklında tutmak icin bilgisayar 156789 uncu byte a 0 ve 1 lerle

5 degerini kaydetti. Artık p nin degeri 156789 oldu.



main()

{

int *p;

int x;

x=5;

p=&x;

printf("%d\n",x);

printf("%d\n",p);

return 0;

}



yukardaki kodu yazıp calıstırırsanız, programın x in degeri olarak 5 i ve

x in tutuldugu memory adresini yani p nin degerini verdigini goreceksiniz.

p nin alacagı deger her bilgisayarda farklı olacaktır. Cunku x degiskeni

RAM deki ilk bos yere yazılacaktır ve bu bilgisayarın calısma durumuna ve

RAM in kapasitesine gore degisir.



Bir degiskene pointer atadıktan sonra o pointerı kullanarak degiskene

istedigimis degisikligi yapabiliriz. p, isaret ettigi degiskenin adresini ifade

ederken, *p, degiskenin degerini ifade eder. yukardaki kodlarda



printf("%d\n",p); komutunu

printf("%d\n",*p); seklinde degistirirsek x degiskeninin

adresi yerine degerinin yani gene 5 in ekrana verildigini goreceksiniz.



Aynı sekilde x in degerini de degistirebiliriz.



*p=6;



yazdıktan sonra x in degeri artık 6 olur.Yani *p ifadesi p pointerının işaret ettigi

degişken anlamına geliyor ve x yerine istedigimiz zaman *p ifadesini kullanabiliyoruz.



Bu noktaya kadar pointerların ne oldugu ve ne ise yaradıklarını ogrendik.

Peki nedir bu pointerları bu kadar onemli yapan, nedir bu pointerların marifetleri ?

Gelelim pointerların marifetlerine ve C deki kullanım alanlarına...



C de tanıttıgımız her şey, degisken, array, fonksiyon... her şey RAM e yazılır

Dolayısıyla RAM e yazılan her şeye RAM adresini taşıyan bir pointer atanabilir.

Yani pointer C de her programda, her algoritmada kullanılabilir.Baslıcalarına deinelim.



Pointerlarla arrayler:



int A[5]



diye bir satırla tanıttıgımız A arrayine beş tane integer(tam sayı) tasıyabilecek sekilde

RAM de yer ayrılır. Program bir integerı aklında tutabilmesi icin 2 yada 4 byte yer ayırır hafızada Dielimki bizim compilerımız 4 byte yer ayırıyor bir integer icin. A arrayine yer

acılması icin 5 * 4= 20 byte lık alan hafızada ayrıldı. Diyelimki RAM de ilk bos

byte 123456 ıncı byte olsun. Bu byte dan baslayarak arrayın elemanları icin 20 bytelık yer ayrılacak. Şu şekilde:



________ 123456 ıncı byte A[0]

________

________

________

________ 123460 ıncı byte A[1]

________

________

________

________ 123464 uncu byte A[2]

________

________

________

________ 123468 ıncı byte A[3]

________

________

________

________ 123472 ıncı byte A[4]

________

________

________





Yukardaki sekilde "________" diye gosterilen yerler RAM deki bir byte ı temsil ediyor.

A[0] icin 4 tane byte ayrılmıs. 123456, 123457, 123458 ve 123459 uncu byte lar...

Ama A[0] in RAM adresi kendisine ayrılan ilk byte olan 123456 dır. Bu aynı zamanda

A arrayinin ilk elemanının adresi oldugu icin A arrayinin de adresi oluyor.

A arrayine bir pointer atamak istersek yapmamız gereken mesela p diye

bir integer pointer ı belirledikten sonra p=A satırını yazmak. A zaten A[5]

arrayının ilk elemanının pointerı oluyor otomatik olarak. Simdi bu yazdıklarımızı

kodlara dokerek acıklayalım:



#incluıde<stdio.h>

main()

{

int *p;

int A[5];

A[0]=10;



printf("%d\n",A);

printf("%d\n",A[0]);

printf("%d\n",*A);



p=A;



printf("%d\n",p);

printf("%d\n",*p);

}


Bu programı calıstırırsak şu sekilde bir cıktı verecektir: (A arrayının adresinin 123456 oldugunu kabul ediyorum)



123456 ---->A

10 ---->A[0]

10 ---->*A

123456 ---->p

10 ---->*p



goruldugu gibi A , A[5] arrayinin adresi olan 123456 degerini veriyor. Cunku A nın kendisi bir pointer.

A[0] , arrayin ilk elemenı ve 10 a esitlenmisti. *A , A pointerının işaret ettigi degiskenin degerini verecek.

Bu da arrayin ilk elemanına işaret ediyor ve 10 degerini ekrana veriyor.p pointrerı, A ya esitlendigi icin

boylece arrayın adresini tasımıs oluyor ve ekrana 123456 veriliyor.*p, 123456 adresindeki degiskenin degerini

verecegine gore *p icin ekrana 10 veriliyor... ( yukarda bahsedilen 123456 degeri sizin bilgisayarınızdaki

ilk bosalan RAM adresine gore degisecektir.)



Bir arrayin adının o arrayin pointerı oldugunu ogrendik. Bunu kullanarak (*A seklinde) arrayin ilk elemanına ulasmayı da

ogrendik. Peki arrayin diger elemanlarına nasıl ulaşacaz ? Diyelim ki p diye bir integer pointerı belirledik ve

p=A dedik. p yi kullanarak A[1] e yani arrayin ikinci elemanına nasıl ulasabiliriz ?



p++;



yazarsak p nin degeri bir artırılacak. p nin degeri ornegimizde 123456 idi. Yeni degeri 123457 mi olacak ?

Hayır

C, bunun bir array pointerı oldugunu bilecek ve bir sonraki array elemanına denk gelecek sekilde p nin degerini artıracak.

Bizim ornegimizde integer arrayı kullandık ve her integer icin 4 byte ayrılmıstı. C, bunu bildigi icin p nin degerini 4 artıracak.



p++;



komutundan sonra p nin degeri 123460 olacak. Bundan sonra *p yazarsak bu ifade 123460 adresinde bulunan degiskenin degerine esit olacak.

yani A[1] e... mesela p yi kullanarak A[1] e bir deger atamak istersek:



p=A

p++;

*p=11;



bu komutlarla A[1] in degeri 11 olacak...



Peki bu arraylerin elemanlarını neden pointer kullanarak deistirelimki ? Neden işimizi uzatalımki ? Direk A[1]=11 yazsak daha kolay olur deilmi



Simdi bunu neden ogrendigimizi gosteriyim...

Fonksiyonları işlemiştik. Mesela



int topla(int a,int b);



seklindfe tanıtılan bir fonksiyon girdi olarak iki tane tam sayı alıyor ve bunların toplamını veriyor diyelim.

Fonksiyona bu sekilde tamsayı girdisi yada cıktısı almak kolay. Peki fonksiyonumun bir array almasını yada bir array vermesini

istersek bunu nasıl yapacaz ? Ponter kullanarak



int topla(int *t,int n);



seklinde bir fonksiyon tanıtalım. Burda *t bir array pointerı olsun, n de arrayın uzunlugu...

Bu fonksiyon, arrayin elemanlarını toplasın ve sonucu versin:



int topla(int *t, int n) //1.satır

{ //2.satır

int i; //3.satır

int toplam = 0; //4.satır

for(i=0; i<n; i++) //5.satır

{ //6.satır

toplam=*t + toplam; //7.satır

t++; //8.satır

} //9.satır

return toplam; //10.satır

} //11.satır

Bu fonksiyonun yaptıgı işi satır satır anlatalım:

1.satırda fonksiyonumuzu yazdık, 2. satırda fonksiyonumuzun yaptıgı işi anlatacagımız { } isaretlerinin ilkini actık.

3. satırda for dongusunde kullanacagımız degiskeni tanıttık. 4. satırda

arrayin elemanlarını toplayacagımız toplam degiskeninin tanıttık ve ilk degerini 0 a esitledik.

5. satırda for dongumuzu yazdık.dongumuz 0 dan baslayıp

arrayin uzunluguna kadar kendini tekrarlıycak. Mesela “int A[3]” diye tanımladığımı uzunluğu 3 olan bir arrayi bu fonksiyona sokacaksak

fonksiyonu şu sekilde kullanacaz main in icinde :

topla(A,3)

burda t, A ya esitlenecek n de 3 e esitlenecek. for dongusu 3 kere donecek.

7.satır da dongu her seferinde toplam degiskenine *t nin degerini ekleyecek.

donguye ilk girildiginde *t arrayin ilk elemanının degeri olacak. Sonra 8. satırda t, bir sonraki elemana

isaret edecek. Donguye tekrar girildiginde bu sefer *t arrayin 2. elemanının degerine esit oloacak... bu sekilde devam ederek toplam degiskenine arrayin her elemanı teker teker eklenecek. 10.satırda elde edilen toplam fonksiyonun cıktısı olacak...



yukardaki kodları birlestirerek bir ornek program yazalım:



#include<stdio.h>



int topla(int *t, int n);



main()

{

int Q[5] = {2,4,6,8,10} ;

int x;

x=topla(Q,5);

printf("%d",x);

return 0;

}



int topla(int *t, int n)

{

int i;

int toplam = 0;

for(i=0; i<n; i++)

{

toplam=*t + toplam;

t++;

}

return toplam;

}




Bu programı calıstırırsanız ekrana 2 4 6 8 ve 10 un

toplamını verecektir, sanırım 30 ediyor



son olarak pointerın pointerı diye bir şey var onu anlatalım:

Pointer da bir degişken olduguna gore ve bilgisayarın pointerın adresini aklında

tutabilmek icin onu da RAM de bir yere yazdıgına gore, bir pointer a da işaret eden bir pointer belirlenebilir.Yani pointerın pointerı… kafalar biraz daha karısacak



int **a;

int *b;

int c;



c=3;

b=&c;

a=&b;



yukardaki kodlarda b pointerı c integerına isaret ediyor, a pointer pointerı da b pointerına isaret ediyor.



a --> b --> c



seklinde...



c nin degeri 3, b nin degeri c nin memory adresi, a nın degeri de b nin memory adresi oluyor.



c degiskeni degeri : 3 , RAM adresi : 123456

b degiskeni degeri : 123456 , RAM adresi : 123460

a degiskeni degeri : 123460 , RAM adresi : 123464



seklinde bir RAM adresleri ve degisken degerleri tablosu oluşacaktır. RAM adreslerini kafadan attım tabiki...



printf("%d",a) ----> 123460 ı verir

printf("%d",*a) ----> 123456 yı verir

printf("%d",**a) ----> 5 i verir



pointerın pointerı iki boyutlu arraylerde kullanılabilir... A[2][3] gibi...

Ama bukadar ayrıntıya girip anlatamıycam yoksa yazının sonu gelmez

Benden size ana hatları ile pointerlar... Ayrıntıları ogrenmek size kalmıs...

Kafanıza takılan ayrıntılar, ogrenmek istediginiz şeyler yada anlamadıgınız noktalar olursa sorun forumda



Buraya kadar kafa karıstırabilecek bir iki şeyden bahsediyim.

Birincisi matemetiksel işlemlerde *p seklinde kullanılan bir pointer carpma işlemi olan

* isareti ile karışmaz merak etmeyin. mesela

a * *b;

seklinde bir ifade a carpı b pointerının işaret ettigi deger anlamına gelir.C, * leri birbirinden ayırmasını bilir merak etmeyin

İkincisi pointerı tanıtırken kullanılan * ile pointerın işaret ettigi degiskenin degeri anlamına gelen *

sempolunu birbirine karıştırmamak gerekir. Gene C buınları karıstırmaz ama siz karıstırabilirsiniz

mesela bir fonksiyonu tanıtırken

fonksiyon(int *p);

yazıldıgında "int *p" kısmında kullanılan * isareti p nin bir integer pointerı oldugunu anlatır.

pointer tanıtma isaretidir.

Misal başka bir fonksiyon tanıtıldıktan ve implement edildikten sonra main in icinde kullanırken mesela:



fonksiyon(*p);



dersek, buradaki * işareti ise p pointerının işaret ettigi degişkenin degeri anlamına geliyor...





Pointerlar sadece intergerlar icin kullanılmaz tabiki... mesela char degiskenlerşi ve string ler icin

de bir iki ornek yazalım:



char A[] = "radres";

seklinde bir string tanımlanınca A bu stringin ilk elemanına işaret eden bir pointerdır.

*A, r yi verir...



p=A;

p++;

yazdıktan sonra *p, a ya esittir.



yada



p=A;

*(p+3)='\0';



dersek



printf("%s",A);



bize “rad” ı verir. Cunku stringin 4. elemanının olan *(p+3) u stringin bitiş elemanı anmlamına gelen '\0' a eşitledik.



pointerlarla ilgili soyliyecegim son şey fonksiyonlarla degisken degerlerini degistirmektir.


DEVAMI ALTTA
__________________
Biz Bu Hallere Düşecek Adammıydık ???
Alıntı ile Cevapla