8. İŞARETCİLER (POINTERS) Verilerin bilgisayar hafızasında tutulduğu fiziki alan adres olarak tanımlanabilir. Adres, hem donanımla hem de yazılımla ilişkilidir. Donanımsal açıdan adres bellekte yer gösteren bir sayıdan ibarettir. Mikroişlemci bellekte bir bölgeye ancak o bölgenin adres bilgisiyle erişebilir. Fiziki olarak bilgilerin yerleşimi işlemciden işlemciye göre değişiklik göstermektedir. Verilerin 0000 adresinden artan sırayla yerleştirilmesine doğrusal adresleme denir. Bazı işlemciler ise bu yerleşim hafızanın en üst kısmından (FFFF adresinden) aşağı doğru olmaktadır. (Intel işlemci tabanlı bilg.) Örneğin, 64 K lık bir belleğin azalan adreslenmesi aşağıdaki biçimde yapılabilir: BELLEK (içerik) ADRES 65535 (FFFF) 65534 (FFFE) 65533 (FFFD)...... 3 2 0 (0000) Adreslemede 16 lık sistem kullanılmaktadır. Her değişken bellekte yer kapladığına göre belirli bir adrese sahiptir. Nesnelerin adresleri, sistemlerin çoğunda, derleyici ve programı yükleyen işletim sistemi tarafından ortaklaşa olarak belirlenir. Nesnelerin adresleri program yüklenmeden önce kesin olarak bilinemez ve programcı tarafından da önceden tespit edilemez. Programcı, nesnelerin adreslerini ancak programın çalışması sırasında (run time) öğrenebilir. Dr. Nihat ÖZTÜRK 1
Göstericilerin Bildirimi Göstericiler adres bilgilerini saklamak ve adreslerle ilgili işlemler yapmak için kullanılan değişkenlerdir. Göstericilerin içlerinde adres bilgileri bulunur. Bu nedenle gösterici ile adres eş anlamlı olarak düşünülebilir. Gösterici bildirimlerinin genel biçimi şöyledir: < Tip > *<Gösterici ismi>; <tür> göstericinin tutacağı adres türüdür. char, int, float... gibi herhangi bir tür olabilir. Burada * göstericiyi ya da adresi temsil etmektedir. Örnek gösterici bildirimleri: float *f; // tanımı ile float değişkenlerin adresini tutabilirsiniz char *s; // tanımı ile char tipindeki değişkenlerin adresi tutabilirsiniz. Göstericiye adres ataması yapılması & işleci : Bir değişkenin adresinin belirlenmesi için kullanılır. Kullanım biçimi: &i : işlemi ise i değişkenin adresini verir. Buna göre adres tutacak değişken (gösterici) tanımlandığına göre artık atama yapılabilir. float a,*ptr; ptr= &a;// deyimi ile, ptr işaretçisi a değişkeninin adresin tutacaktır. int tam, *gst; gst=&tam; // tam değişkenin adresi tutulur. Dr. Nihat ÖZTÜRK 2
Bir programda şu tanımlamalar yapılmış olsun, 1 int a,*b; // a ve işaretçi olarak b değişkenleri tanımlanmış 2 char ch, *kr; // ch ve işaretçi olarak kr değişkeni tanımlanmış 3 float say; // float değişken tanımlanmış. 4 a=10; // a değişkenine değer ataması yapılmış 5 b=&a; // b işaretçisine a nın adresi atanmış 6 ch= A ; 7 kr=&ch; 8 say=3.14; Söz konusu tanımlama ve programın yazımından sonra hafıza adresleri ve içerikleri şöyle verilebilir. (Adreslemenin doğrusal olduğu ve değişkenler için ardı ardına alan ayrıldığı varsayılmıştır). Adres İçeriği Bellek Adı Adres İşlenen Komut Rastgele Değer a değ. için ayrılır FEEE Hex 1.Satırın işlenmesi Rastgele Değer *b deg FEEC Rastgele Değer ch değ. için ayrılır FEEA Hex 2.Satırın işlenmesi Rastgele Değer *kr deg FEE9 Rastgele Değer say değ. için ayrılır FEE8 Hex 3. Satırın işlenmesi Adres İçeriği Bellek Adı Adres İşlenen Komut 10 a FEEE Hex 4.Satırın işlenmesi FEEE *b FEEC 5 Satırın işlenmesi 65 (A nın ASCII ch FEEA Hex 6. Satırın işlenmesi kodu) FEEA *kr deg FEE9 7. Satırın işlenmesi 3.14 say FEE8 Hex 8. Satırın işlenmesi Dr. Nihat ÖZTÜRK 3
Örnek1 clrscr (); int a=5; int *ptr; //işaretçi bildirimi ptr=&a; //işaretciye adres ataması printf ("bir sayı giriniz"); scanf("%d",ptr); //işaretçinin tuttuğu adres içeriği dolduruluyor. printf("a sayısı=%d\n",a); a=10; printf("a sayısının adresi =%x\n",&ar); printf("ptr nin adresi=%x\n",&ptr); printf("a sayısının sayısal degeri=%d\n",ar); printf("a sayısına pointer ile erişim =%d\n",*ptr); getch (); Örnek2 //int tipi diziye 5 eleman girilmektedaha sonra bu sayılar *ptr // kullanılarak goruntulenmektedir. clrscr (); int x[10],i; int *ptr; ptr=x;//ptr=x[0] seklindede yazılabilir. for (i=0;i<5;i++) printf ("%d. sayıyı giriniz:",i+1); scanf("%d",&x[i]); printf("\n"); for (i=0;i<5;i++) printf("%d.sayı=%d\n",i+1,*ptr++); getche (); Dr. Nihat ÖZTÜRK 4
İşaretçi Aritmetiği İşaretçi değişkenler üzerinde toplama ve çıkartma işlemleri (++, --) geçerlidir. Ancak eklenecek değer tamsayı olmalıdır. İşaretçi değişkenin değeri 1 arttırıldığı zaman değişken bir sonraki veri bloğunu işaret eder. Değişkenin alacağı yeni değer işaretçi değişkenin ne tip bir veri bloğunu işaret ettiğine bağlıdır. int *iptr, i; iptr = &i; iptr++; i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir. iptr nin değeri 1002 olur. ( int değeri işaret ettiği için) Örnek3 //pointer aritmetigi #include<stdlib.h> clrscr (); int *p1,d1,d2; p1=&d1; d1=444; d2=888; printf ("%d %d %p\n",d1,*p1,p1); *p1--; printf ("%d %d %p\n",d1,*p1,p1); (*p1)++; printf ("%d %d %p\n",d1,*p1,p1); d1='d'; p1=&d1; printf ("%c\n",*p1); (*p1)--; printf ("%c\n",*p1); getche (); /* 444 444 FFF4 444 888 FFF2 444 889 FFF2 */ Dr. Nihat ÖZTÜRK 5
Örnek4: //Argumanı adres olan fonksiyon void degistir(int *,int *); int x,y; printf ("bir sayı giriniz\n"); scanf("%d",&x); y=23; printf ("girdiginiz sayı x=%d ve y=%d\n",x,y); degistir (&x,&y); printf ("simdi x=%d ve y=%d",x,y); void degistir (int *a,int *b) int g; g=*a; *a=*b; *b=g; Örnek 5 //dizilerin fonksiyonlara parametre yolu ile geçirilmesi int max(int *a,int b) int val,k; val=a[0]; for (k=1;k<b;++k) if (val<a[k]) val=a[k]; return val; Dr. Nihat ÖZTÜRK 6
clrscr (); int x[10]=2,33,0,5,6,10,-9,5,12,13; int i; //dizinin ismi dizinin bellekte başlangıç adresini gösterir. i=max(x,10);//diziyi fnk geçirmek için dizinin başlangıç adresini //ve uzunlugunu geçirmek yeterlidir. printf ("en buyuk sayı=%d\n",i); getche (); Örnek6://pointer adresi taşıyan pointer #include<stdlib.h> void main (void) clrscr (); int **pp1,*p1,i1; int **pp2,*p2,i2; p1=&i1; pp1=&p1; p2=&i2; pp2=&p2; *p1=60; i1=30; i2=45; //*(*(pp1+i1)+i2=5 mumkun; *(p1+i1)=5; **pp2=(*(p1+i1)+i2); printf ("%p %p %p\n",pp1,p1,&i1); printf ("%d %d %d\n",**pp1,*p1,i1); printf ("\n"); printf ("%p %p %p\n",pp2,p2,&i2); printf ("%d %d %d\n",**pp2,*p2,i2); getche (); Dr. Nihat ÖZTÜRK 7
Örnek7:Header dosya oluşturma baslik.h #include <stdio.h> #define A main() #define B #define C #define D printf("bu bir denemedir\n") #define E ; #include baslik.h A B D E C KAYNAKLAR Şevki DEMİRBAŞ, Oğuz ÜSTÜN ve Nihat ÖZTÜRK, Beltek kursu ders notları, Gazi Üniversitesi Pektaş H., C Dili Kullanarak Bilgisayar Programlama, KOU EHM, Ders Notları. Sistem Programlama ve İleri C Uygulamaları. Dr. Nihat ÖZTÜRK 8