BİLİŞİM - BİLGİSAYAR - EĞİTİM
  İşaretçiler (Pointers)
 

9.   Pointer (gösterici, işaretçi):

9.1 Tanımlanması ve Kullanımı:

    Bir veri bloğunun bellekte bulunduğu adresi içeren (gösteren) veri tipidir. Tanımlama biçimi:

     veri tipi  *p;

p değişkeni <veri tipi> ile belirtilen tipte bir verinin bellekte saklandığı adresi içerir.

 

     int *iptr;

     float *fptr;

 

Bu kadar tanımla sonucunda bellekte p değişkeni mevcuttur. Ancak işaret ettiği veri bloğu yoktur. Bunun için iki yol vardır. Birincisi  kullanılan herhangi bir değişkeni işaret etmek, ikincisi ise  veri bloğunu boş belleği kullanarak oluşturmak.

 

1.  İşaretçi değişkenin var olan bir değişkenin bulunduğu adresi göstermesi.

Bu işlemi yapabilmek için var olan değişkenin adresinin bilinmesi gerekmektedir.

& işleci : Bir değişkenin adresinin belirlenmesi için kullanılır. Kullanım biçimi:

 

&değişken

&i  : i değişkenin adresini verir.

main()

{

  int i;

  int *iptr;

  i = 5;

  iptr = &i;

  clrscr();

  printf("i değişkeninin adresi    %pn", &i);

  printf("iptr değişkeninin değeri %pn", iptr);

}

 

Bellek modeline göre SSSS:OOOO veya OOOO biçiminde adres yazar.

8FF8:1000

 

2. Veri bloğunu boş belleği kullanarak oluşturmak.

Bu yolla veriler için dinamik yer ayırılır. Bunun için malloc işlevi kullanılır

 

void *malloc(n) : Boş bellekten n byte yer ayırıp başlangıç adresini döndürür.

iptr = (*int) malloc(2);

!!!!!!!!!    Daha sonra dönüş yapılacak. sizeof,  cast işleci (*tip) ...

 

Veriye işaretçi değişken yoluyla erişim

Bir işaretçinin gösterdiği adresteki veriye erişmek için işaretçi değişkeninin önüne * karakteri konur.

 

main()

{

  int i;

  int *iptr;

  iptr = &i;

  *iptr = 8;

  printf("i değişkeninin değeri %dn", i);

  printf("iptr adresinin içeriği %dn", *iptr);

}

 

Ekranda çıktı :

 

i değişkeninin değeri 8

 

iptr adresinin içeriği 8

 

!!! İşaretçi değişkenin gösterdiği adresin içeriği değişken ilklendirmeden kullanılmamalıdır

 

 

 

9.2 İş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şsaret 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;                   i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.

iptr++;                       iptr nin değeri 1002 olur. (  int değeri işaret ettiği için)

 

aynı örneği double için yaparsak

 

double *iptr, i;

...

iptr = &i;                   i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.

iptr++;                       iptr nin değeri 1008 olur. (  double değeri işaret ettiği için)

int *iptr, i, j;

...

iptr = &i;                   i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.

*(iptr+4)=2;             1008 adresinin içeriğini 2 yapar.

 

!!! Arttırma işaret edilen veri bloğuna göre yapılır Yani bir sonraki veri bloğunun gösterilmesi sağlanır.

 

iptr++ ;       bir sonraki veri bloğunu göster

(*iptr)++;   iptr değişkeninin gösterdiği adresteki değeri 1 arttır

 

9.3 İşaretçiler ve Diziler:

 

İşarteçiler üzerinde geçerli aritmetik yardımıyla dizilere işaretçi değişkenler ile erişmek mümkündür.

 

#include <stdio.h>

main()

{

  int i[10], j;

  int *iptr;

  for (j=0; j<10; j++)

       i[j]=j;

  /* Dizinin başlangıç adresine erişmek için ilk elemanın adresi kullanılabilir  &i[0]  veya doğrudan */

  iptr = i;

  clrscr();

  for (j=0; j<10; j++) {

     printf("%d ", *iptr);

      iptr++;

  }

  printf("n");

/* iptr artık dizinin başını göstermez */

  iptr = i;

  for (j=0; j<10; j++)

      printf("%d ", *(iptr+j));

printf("n");

/* iptr hala dizinin başını gösterir */

  getch();

}

 

Örnek 9.3.1: İşaretçi ve dizgi kullanımı.

 

#include <stdio.h>

main()

{

  char *a="1234567890";

  char b[11];

  char *p1, *p2;

  printf("%sn", a);

  p1 = a;

  p2 = b;

  while (*p1 != '') {

      *p2 = *p1;

      p1++;

      p2++;

  }

  printf("%sn", b);

}

 

9.4 İşlevleri Referans Yoluyla Çağırma:

Şu ana yazdığımız işlevlerde gönderilen parametrelerin (diziler hariç) değerlerinin değiştirilmesi mümkün değil idi. İşlev çağırıldığı zaman parametrelerin bir kopyası çıkartılıp işleve gönderiliyordu. Bir işlevin birden fazla değer gönderebilmesi için işaretçilere gereksinimiz vardır.

 

void arttir(int);

main()

{

  int i;

  i = 5;

  printf("öncesi %dn", i);

  arttir(i);

  printf("sonrası %dn", i);

  getch();

}

void arttir(int k)

{

  k++;

}

 

Çıktı :

öncesi 5

sonrası 5

 

Gönderilen parametrenin kopyası işleve gönderildiği için işlev içerisinde yapılan değişiklikler işlevin çağırıldığı yeri etkilemez. Eğer parametredeki değişikliklerin işlevin çağırıldığı yerde de geçerli olmasını istiyorsak işleve parametrenin adresini göndermek gerekir.

 

void arttir(int*);

main()

{

  int i;

  i = 5;

  printf("öncesi %dn", i);

  arttir(&i);

  printf("sonrası %dn", i);

  getch();

}

void arttir(int *k)

{

  (*k)++;

}

 

öncesi 5

sonrası 6

 

Örnek 9.4.1: Sayısal dizgiyi tamsayıya dönüştüren işlevde iyileştirme. Geçersiz karakterin konumu da verilsin.

 

int deger(char *s, int *konum)

konum = -1 ise tüm karakterler rakam

            >=0 ise geçersiz karakterin konumu

 

Örnek 9.4.2 : Sıraya dizme. Yer değişikliği işlevde ve parametrelere referans yolu ile erişim.

 

#include <stdio.h>

#include <conio.h>

#define N 20

void degistir (int *, int *);

main()

{

   int s[N];

   int i, k;

clrscr();

   for (i=0; i<N; i++) {

       s[i] = rand() % 100;

       printf("%4d",s[i]);

   }

   printf("n");

   k=1;

   do {

      k=0;

      for (i=0; i<N-1; i++)

          if (s[i] > s[i+1]) {

            degistir (&s[i], &s[i+1]);

            k = 1;

          }

   } while (k);

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

       printf("%4d",s[i]);

   printf("n");

   getch();

}

void degistir (int *a, int *b)

{

  int gec;

  gec = *a;

  *a = *b;

  *b = gec;

}

 

!!! Dizilerde işaretçi olduğu için a değişkeni bir dizi(veya işaretçi ise)

a[i] ile *(a+i) ifadeleri aynı anlamı taşır.

 

Örnek 9.4.3: İşleve gönderilen dizinin işlev içerisinde işaretçi olarak kullanımı.

 

#include <stdio.h>

#include <conio.h>

#define N 5

float ort (int *);

main()

{

  int s[N];

   int i, k;

   clrscr();

   for (i=0; i<N; i++) {

       s[i] = rand() % 100;

       printf("%4d",s[i]);

   }

   printf("n");

   getch();

}

float ort (int *a)

{

  int i;

  float t = 0;

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

      t = t + *(a+i);

  return t/N;

}

 

Örnek 9.4.5: işleve gönderilen işaretçinin işlev içerisinde dizi olarak kullanımı .

 

void malloc(n):  En az n byte uzunluğunda bellekten yer ayırır. İşlevin değeri

                               >0 ise bloğun bellekteki yeri, NULL yer yok demektir.

int *i;

i = (int *) malloc(2000) ;    2000 byte yer ayırıp bloğun başlangıç adresini i 'ye atar

                                             ( 1000 elemanlı int dizisi )

double *x;

x = (double *) malloc(8*2000);  2000 elemanlı double dizi

sizeof(n) : n ifadesinin/tipinin byte olarak uzunluğunu verir.

i = (int *) malloc(1000*sizeof(int)) ;    1000 tane int değer içerecek bellek uzunluğu

x = (double *) malloc(2000*sizeof(double));  2000 elemanlı double dizi

void free (void *block) : mallock işlevivi tersi. Block değişkenin tuttuğu yeri boş belleğe gönderir

#include <stdio.h>

#include <conio.h>

#define N 8

float ort (int []);

main()

{

   int *s;

   int i, k;

   s = (int *) malloc(2*N);

   clrscr();

   for (i=0; i<N; i++) {

       s[i] = rand() % 10;

       printf("%4d",*(s+i));

   }

   printf("n");

   printf("Ortamala = %.2fn",ort(s));

getch();

}

float ort (int a[])

{

  int i;

  float t = 0;

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

      t = t + a[i];

  return t/N;

}

 

Örnek 9.4.6 : Bir dizinin elemanlarının işaretçi olması.

 

Daha önce yapılan bir örnekte ay isimleri bir dizide saklanmıştı.

main()

{

  char *aylar[] = {"", "Ocak", "ªubat", "Mart", "Nisan",

                   "Mayıs", "Haziran", "Temmuz", "Ağustos",

                   "Eylül", "Ekim", "Kasım", "Aralık"};

  int i;

  printf("Ayın sırasını gir "); scanf("%d", &i);

  if (i>0 && i<13)

     printf("%sn", aylar[i]);

  getch();

}

 

Benzer şekilde

                float *a[100];

tanımlaması her bir elemanı bellekte bir 'float' sayıyı gösteren işaretçi olan 100 elemanlı bir dizidir.

 

Örnek 9.4.7 : Bir işaretçinin adresini içeren işaretçiler.

 

main()

{

  int i;

  int *iptr;

  int **iptrptr;

  i = 5;

  iptr = &i;

  iptrptr = &iptr;

  clrscr();

  printf("    i    ve    &i    :  %d   %pn", i, &i);

  printf("  *iptr  ve   iptr   :  %d   %pn", *iptr, iptr);

  printf("*iptrptr ve  iptrptr :  %p   %pn", *iptrptr, iptrptr);

  getch();

}

 

Ekrana çıktı:

        i    ve    &i     :  5   8FDD:1000

    *iptr  ve   iptr    :  5   8FDD:1000

*iptrptr ve  iptrptr :  8FDD:1000   8FDD:0FFC

9.5 İşaretçiler ve Yapılar:

  Bir işaretçi işleve parametre olarak gönderildiğinde basit değişken gibi değişkenin kopyası alınıp gönderiliyordu. Yapının büyük olduğu durumlarda bu da sorun çıkartır. İşaretçinin bir yapı verisini göstermesi.

 

   struct ogrenci{

     char no[10];

     int  notu;

   };

   struct ogrenci *a

 

Tanımlamasında a değişkenini oluşturan alanlara erişmek için, bilinen yol:

 

                *a.notu=56;

 

              strcpy((*a).no, "95001");

 

Bunun farklı kullanımı:

                a->notu=56;

 

               strcpy(a->no, "95001");

 

 

 

 

Örnek 9.5.1 :  Yapının adresinin işleve gönderilmesi.

 

#include <stdio.h>

typedef struct {

    char adi[35];

    char adres1[40];

    char adres2[40];

    char tel[15];

    float borc;

} kisiler;

void yaz(kisiler *z);

main()

{

   kisiler  a;

   clrscr();

   printf("Adını gir  : "); gets(a.adi);

   printf("Adres-1    : "); gets(a.adres1);

   printf("Adres-2    : "); gets(a.adres2);

   printf("Telefonu   : "); gets(a.tel);

   printf("Borcu      : "); scanf("%f", &(a.borc));

   yaz(&a);

}

void yaz(kisiler *z)

{

  clrscr();

  printf("Adı        : "); puts(z->adi);

  printf("Adresi     : "); puts(z->adres1);

  printf("           : "); puts(z->adres2);

  printf("Telefonu   : "); puts(z->tel);

  printf("Borcu      : "); printf("%.0fn", z->borc);

}

 
 
  Bugün 127 ziyaretçi (194 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