Ba?lant?lar:

  • 12May

    Önceki yazımda for döngüsünün en yaygın şeklini ele almıştım. Ancak for‘un gücünü, esnekliğini ver bilirli programlama durumlarına uygulanabilirliğini artıran bazı varyasyonları mümkündür… Devam?n? oku »

    Etiketler: , ,

  • 01May

    for döngüsünün genel tasarını tüm prosedürer dillere bir şekilde yansıtılmıştır. Ancak C’de for döngüsü umulmadık bir esneklik ve güç sağlar.

    for ifadesi genel oalrak şu şekildedir:

    for(başlama; koşul; artırım) ifade;

    for döngüsünün birçok varyasyonu söz konusudur. Ancak, en yaygın şekli şöyle çalışır. başlama, döngü kontrol değişkenini ayarlamak için kullanılan bir atama ifadesidir. koşul, döngüden ne zaman çıkılacağını belirleyen ilişkisel bir deyimdir. artırım, döngünün her tekrarında döngü kontrol değişkeninin nasıl değişeceğini tanımlar. bu üç ana bölümü noktalı virgül ile birbirinden ayırmalısınız. for dögüsü, koşuk true(doğru) olduğu sürece çalışmaya devam eder. koşul false(yanlış) olduğu anda, program çalışmasına for’u takip eden ifadeden devam eder.

    Aşağıdaki programda, 1 ile 100 arasındaki sayıları ekrana basmak için bir for döngüsü kullanılır:

    #include<stdio.h>

    int main(void)

    {

    int x;

    for(x=1; x<=100; x++) printd(”%d”,x);

    return 0;

    }

    döngüde x, ilk önce 1 olarak ayarlanır, sonra 100 ile karşılaştırılır. c, 100′den küçük olduğu için printf() çağrılır ve döngü tekrarlanır. Bu x’in 1 arttırılmasına neden olur ve x, hala 100′ e eşit ya da 100′den küçük mü diye tekrar test edilir. Eğer öyleyse, printf() çağrılır. Bu süreç, x 100′den büyük olana dek(döngü sona erer) tekrarlanır. Bu örnekte x, döngünün her tekrarında değişken ve kontrol edilen döngü kontrol değişkenidir.

    Aşağıdaki örnek, bir ifade bloğunu tekralayan bir for döngüsüdür:

    for(x=100; x!)65; x-= 5)

    { z= x*x;

    printf(”The square of %d, %d”, x,z);

    }

    x, 65′e eşit olana kadar hem x’in karesi, hem de printf() çağrısı çalıştırılır. Döngünün negatif yönde çalıştığına dikkat edin: x’e ilk değer olarak 100 atanır ve döngünün her tekrarında x’den 5 çıkartılır.

    for döngülerinde koşul testi daima döngünün başında yapılır. Bu, döngüye başlarken eğer koşul false(yanlış ise, döngnün içindeki kodun hiç çalıştırılmayabileceği anlamına gelir. Örneğin aşağıdaki örnekte döngü asla çalışmayacaktır, çünkü döngüye girişte x ve y birbirine eşittir:

    x=10;

    for(y=10; y!=x;++y) printf(”%d”, y);

    printf(”%d”,y); /* bu , çalışacak tek printf() ifadesidir*/

    Bu, koşullu deyimin false olarak hesaplanmasına neden olacağı için ne döngünün gövdesi ne de artırım kısmı çalıştırılmaz. dolayısıyla, y halen 10 değerindedir ve kod parasının ürettiği tek çıktı, ekrana bir kez basılan 10 sayısıdır.

    Etiketler: , , ,

  • 30Nis

    IF Koşul-Şart Kullanımı

    if(şart)
    işlem1;
    else
    işlem2;

    Şart geçerli olduğu müddetce işlem1 işlem yapar,şart geçerli değilse else den sonra gelen cümle yani işlem2 işlem görecektir.
    Eğer şart doğru olduğu müddetce yapılan işlemler birden fazlaysa işlemler {} içine alınır, durum aşağıdaki gibi olur:

    if(şart)
    {
    işlem;
    işlem;
    işlem;
    }
    else
    işlem;

    Örnekler:

    örnek1:Bir öğrenciye ait 2 tane not kalvyeden girilecek ve ortalaması hesaplanacak, eğer ortalama 45den büyükse ekrana geçti, küçükse kaldı yazdıran program.
    #include
    #include
    float ortalama;
    int not1,not2;
    int main()
    {
    printf(”1.notu giriniz”);
    scanf(”%d”,&not1);
    printf(”2. sayiyi giriniz”);
    scanf(”%d”,&not2);

    ortalama=((not1+not2)/2));
    if(ortalama<=45)
    printf(”gecti”);
    else
    printf(”kaldi”);

    return 0;
    }

    Yukarda printf ile ekrana sayı girilemsi için mesaj veriliyor.scanf ilede klavyeden not girişi yapılıyor.
    if(ortalama<=45) eğer 45e eşit veya 45den büyükse if deyiminin altındaki işlem yapılıyor yani printf ile ekrana geçti yazdırılıyor.eğer koşul doğru değilse yani ortalama 45 den küçükse koşul doğru olmuyor veya bir başka değişle koşul sağlanmıyor ise else’nin altındaki komut çalıştırılır,yani printf ile ekrana kaldi yazdırılır.
    return 0; komutuda geri dönüş değeri 0 demek.Bunu ilerde bir programda anlatacağımı umuyorum şuan kafanızı karıştırmıyım :)

    Etiketler: , , ,

  • 22Nis

    6.1 Fonksiyon tanimi

    Fonksiyon blogunun yapisi;

    dönüs_tipi fonksiyon_adi(parametre listesi)
    {
    islem blogu
    }

    dönüs_tipi, fonksiyonun sonucu, fonksiyonun çagirildigi noktaya gidecek olan degerin tipini belirtir. Fonksiyonlar dizi hariç her tür veri tipi döndürebilirler. Parametre listesi ise, fonksiyon çagirilirken kulanilmasi gereken degiskenler ve onlarin veri tipleridir. Fonksiyon parametre kullanmadan da çagirilabilir -bos bir parametre listesi için void veri tipinden faydalanilir.
    Degisken tanimlamada ayni veri tipine sahip degiskenler, birbirinden virgül ile ayrilarak tanimlanabiliyordu. Fakat fonksiyonlara ait parametre tanimlamasinda bu yöntem kullanilmaz. Parametre tanimlamalarinda her parametre, kendi ver tipi iel tanimlanir. Yani;

    f(int i, int k, float f)

    dogru iken

    f(int i, k, float f)

    yanlistir. Ikinci örnekte k degiskeni kendi veri tipine sahip olmalidir.

    6.2 Fonksiyonun tanim alani

    Her fonksiyon, kendi basina bir kod blogudur. Bu yüzden fonksiyonalr kendi tanim alanlarini olustururlar. Yani fonksiyonun kodu kendine özeldir ve program içinde yer alan herhangi bir ifade tarafindan bu kod parçasina erisilemez. Örnegin bir fonksiyon içinde goto’yu kullanarak baska bir fonksiyonun kodunun herhangi biryerine atlama yapilamaz. Fonksiyonu olusturan kod parçasi programdan saklanir ve bu kisim global degisken kullanmadikça ne programin bir kismi tarafindan etkilenir ne de programin baska bir kismini etkileyebilir.

    Bir fonksiyonun içinde tanimlanmis degiskenlere local (yerel) degiskenler adi verilir. Local degiskenler, tanimlandigi fonksiyon çagirildiginda devreye girer ve fonksiyonun çalismasi sona erince kullanimdan kaldirilir. Bu yüzden local bir degisken fonksiyonlar arasinda deger tasimak için kullanilamaz. Deger tasimak için parametreler ve dönüs degerleri kullanilir.

    6.3 Fonksiyon argümanlari

    Eger fonksiyon argüman alacaksa bunlar parametre listesinde tanimlanmalidir. Örnegin;

    int is_in(char *s, char c)
      {
      while(*s)
      if(*s==c) return 1;
      else s++;
      return 0;
      }

    is_in fonksiyonunun s ve c olmak üzere 2 parametresi vardir. Bu fonksiyon verilen c karakterinin, s stringinde olup olmadigini kontrol eder.

    Parametreler fonksiyonlar arasinda deger tasiam görevini yerine getiriyor olsalar da, fonksiyon içinde local degisken gibi davranirlar. Parametreler’e deger atanabilir veya bir ifade içinde kullanilabilirler.

    C’de fonksiyona parametre gönderme islemi 2 ayri sekilde yapilir: Deger ile ve referans ile çagirma.

    6.3.1 Deger ile çagirma

    Deger ile çagirmada, fonksiyondan kullanilan degilskene argümanin degeri atanir. Bu durumda, fonksiyon içinde argüman üzerinde yapilan islemlerin argümanin çagirilan yerdeki degerini üeridne bir etkisi yoktur. Örnegin;

    #include
    int sqr(int x)
      {
      x = x*x;
      return(x);
      }
    void main(void)
      {
      int t=10;
      
      printf(”%d %d”, sqr(t), t);
      }

    kod parçasi gözönüne alindiginda, sqr fonksiyonuna parametre olarak verilen t degiskeninin degeri, fonksiyon içinde x’e atanmistir. x=x*x islemi yapildiginda degisen fonksiyon içinde local degisken olarak kullanilan x’in degeridir. Yani ana programdaki printf satirinin sonucu “100 10” dur.

    6.3.2 Referans ile çagirma

    Referans ile çagirma, deger yerine, gönderilecek parametrenin adresini gönderme yöntemidir. Fonksiyona gönderilen argüman bir deger degil bir adrestir - yani fonksiyon içinde bu adres kullanilarak,gönderilen argümanlarin degerleri degistirilebilir.

    Pointer’larin fonksiyona argüman olarak gönderilmesi, diger tipler ile aynidir. Örnek program, adresleri verilen 2 sayinin degerlerini degistirir;

    #include
    void swap(int *x, int *y)
      {
      int temp;
      temp = *x; /* save the value at address x */
      *x = *y; /* put y into x */
      *y = temp; /* put x into y */
      }
    void main(void)
      {
      int i, j;
      i = 10;
      j = 20;
    printf(”i and j before swapping: %d %dn”, i, j);
    swap(&i, &j); /* pass the addresses of i and j */
    printf(”i and j after swapping: %d %dn”, i, j);
      }

    Bu örnekte swap() fonksiyonu, degiskenlerin degerlerini degistirebilir çünkü degiskenler fonksiyona deger ile degil referans ile, yani pointer ile gönderilmistir. Adres göndermek için & operatörünün kullanildigina dikakt edilmelidir.

    6.3.3 Fonksiyona dizi gönderme

    Fonksiyona parametre oalrak dizi gönderilmek istendiginde yapilan sey fonksiyona dizinin adresini göndermektir. Bunun sebebi, dizi adlarinin, dizinin hafizadaki baslangiça adresini vermesidir. Fonksiyon çagirilirken bu bir deger ile çagirilma gibi görünse de, aslinda referans ile çagirmadir ve fonksiyon içinde, gönderilen parametre üzerinde degisiklik yapilabilir. Örnegin;

    #include
      #include
      void print_upper(char *string)
      {
      register int t;
      for(t=0; string[t]; ++t) {
      string[t] = toupper(string[t]);
      putchar(string[t]);
      }
      }
      void main(void)
      {
      char s[80];
      printf(”Enter a string: “);
      gets(s);
      print_upper(s);
      printf(”ns is now uppercase: %s”, s);
      return 0;
      }

    print_upper() fonksiyonu, gönderilen stringin karakterleriin teker teker denk gelen büyük harfe çevirir ve ekrana yazar. Burada parametre olarak gönderilen string’in üzerinde degisiklik yapilmaktadir. Eger stringin içeriginin degismesi istenmiyorsa, ekrana yazdirma islemi

    void print_upper(char *string)
      {
      register int t;
      for(t=0; string[t]; ++t)
      putchar(toupper(string[t]));
      }

    fonksiyonu ile yapilabilir.

    6.4 argc ve argv - main() fonksiyonunun parametreleri

    Genelde yazilan programlara deger göndermek gerekebilir. Bu islem komut satirindan, programin adi ile deger göndererek yapilir. Program adi ile birlikte gönderilen degerler, main() ana fonksiyonuna gönderilen parametreler olarak algilanir. Komut satiri argümanlarina , UNIX’te C kodu derelyicisinin kullanimi örnek verilebilir;

    cc c_program_adi

    C’de, programa argüman göndermek için iki özel degisken tanimlanmistir: argc ve argv. Bu iki degisken komut satirindan argüman almak için kullanilir. argc degiskeni, programa gönderilen argüman sayisini tutar. Bu deger her zaman 1’den büyüktür çünkü program adinin kendisi de bir argüman olarak kabul edilir. argv ise, karakter pointer’lari tutan bri diziyi gösteren pointer’dir. Bu dizideki her pointer, komut satirindan girilen argümanlardan birini göstermektedir.Komut satirindan girilen her agüman string olarak degerlendirilir. Eger bir sayi kullanilacaksa, bu önce uygun string formatina çevrilmelidir.

    Örnek program ‘Merhaba’ dan sonra verilen ismi ekrana yazdirir;

    #include
      #include
      void main(int argc, char *argv[])
      {
      if(argc!=2) {
      printf(”You forgot to type your name.n”);
      exit(1);
      }
      printf(”Hello %s”, argv[1]);
      }

    Koda dikkat edeilecek olunursa, ana fonksiyonun diger örneklerdeki gibi void main(void) olarak degil, void main(int argc, char *argv[]) olarak tanimlandigi görülür. Bu standart fonksiyon tanimlama sekline uygundur ve burada main fonksiyonu int tipinde argc ve char* tipinde bir argv dizisini argüman olarak alir. Programa girildiginde yapilan kontrol, argüman sayisinin dogru olup olmadiginin kontrolüdür. Bu programa test adi verilip derlenirse, programi çagirma sekli,

    test isim

    seklinde olacaktir. Komut satirinda her argüman bosluk (space) karakteri ile ayrilir. Örnegin;

    test ad1 ad2

    2 argüman aliyorken, bu satir;

    test ad1,ad2

    olarak yazilirsa bir argüman alir. argv argümaninin, char *argv[] olarak tanimlanmasi, argüman olarak verilen dizinin eleman sayisinin belli olmadigini ifade eder. Bu dizinin ilk elemani, yani argv[0], programin adini verir. Yani programa verilen gerçek argümanlar, dizinin 2. gözünden itibaren baslar.

    Bri diger örnek de, verilen bir sayidan geriye dogru sayan bir program;

    #include
      #include
      #include
      #include
      int main(int argc, char *argv[])
      {
      int disp, count;
      if(argc<2) {
      printf(”You must enter the length of the countn”);
      printf(”on the command line. Try again.n”);
      exit(1);
      }
      if(argc==3 && !strcmp(argv[2], “display”)) disp = 1;
      else disp = 0;
      for(count=atoi(argv[1]); count; –count)
      if(disp) printf(”%dn”, count);
      putchar(’a'); /* this will ring the bell */
      printf(”Done”);
      }

    Bu programa sinir sayinin yaninda, geri sayimi ekranda gösterip göstermeyecegini belirten bir de komut verilir. Eger bu komut ‘display’ ise, geri sayim ekranda gösterilir.

    argc ve argv parametreleri, genelde bir programin ilk çalistirilma aninda, bazi opsiyonlar veya kullanilacak dosyalarin adlarini vermek için kullanilir. argc ve argv isimlerini kullanma zorunlulugu yoktur ama bu kullanim geneldir. Bunlar yerine programci kendi istedigi herhangi bir ismi kullanabilir.

    6.5 return ifadesi

    return ifadesinin 2 ayri görevi vardir: Biri, daha önce akis kontrolünde de bahsedilen bir fonksiyondan çikma, digeri de bulundugu fonksiyondan bir deger döndürme. Aslinda, her iki görevi de aynidir çünkü return ifadesi bir deger döndürmeden fonksiyondan çikma islemini gerçeklestiremez.

    6.5.1 Fonksiyondan dönüs

    Kontrolün, fonksiyondan çagirildigi yere dönmesi 2 sekidle olur: birincisi fonksiyonun çalismasinin sona ermesi, ikincisi ise return ifadesi ile. Asagidaki örnekte, kontrol fonksiyonun isi bittigi için ana programa döner;

    void pr_reverse(char *s)
      {
      register int t;
      for(t=strlen(s)-1; t>=0; t–) putchar(s[t]);
      }
      void main(void)
      {
      pr_reverse(”I like C”);
      }

    Burada fonksiyon, parametre olarak verilen stringi tersten yazdirdiktan sonra, main fonksiyonuna döner. Genele fonksiyonalr bu sekilde kodlanmazlar. Hatta bir fonksiyon farkli durumlara göre farkli degerler döndürebilecek sekilde kodlanir. Örnegin;

    int find_substr(char *s1, char *s2)
      {
      register int t;
      char *p, *p2;
       for(t=0; s1[t]; t++) {
      p = &s1[t];
      p2 = s2;
       while(*p2 && *p2==*p) {
      p++;
      p2++;
      }
      if(!*p2) return t; /* 1st return */
      }
      return -1; /* 2nd return */
      }
      void main(void)
      {
      if(find_substr(”C is fun”, “is”) != -1)
      printf(”Substring is found.”);
      }

    Bu programdaki find_substr, verilen bir string içinde, isetnilen ikinci bir string geçiyorsa bunun baslangiç adresini, eger geçmiyor ise -1 döndürür. Görüldügü gibi 2 ayri return ifadesi kullanilmistir ve bu ifadelerden biri her defasindafarkli deger döndürebilecek sekilde kodlanmistir.

    6.5.2 Deger döndürme

    void olarak tanimlanmamis her fonksiyon return ifadesi ile bir deger döndürmek zorundadir. Eger fonksiyon void tanimlanmadigi halde return ile bir deger döndürmüyorsa, garbage value döndürüyor denir.

    Fonksiyonlar deger döndürebildikleri için, dönüs degerinin tipine göre, program içindeki ifadelerde kullanilabilirler. Bu yüzden asagidaki yazimlar dogrudur;

    x = power(y);
      if(max(x,y) > 100) printf(”greater”);
      for(ch=getchar(); isdigit(ch); ) … ;
    Fonksiyonlar çagirildiklari noktalarda bir deger ifade ettikleri için, atama islemlerinde sol tarafta bulnamazlar. Örnegin;

    swap(x,y) = 100; /* incorrect statement */

    yanlis bir yazimdir.

    Program yazarken genel anlamda 3 çesit fonksiyon kullanilir:

    Birinci tip fonksiyonlar hesap islemleri yaparlar. Fonksiyon parametre olarak verilen degerler üzerinde bir islem yapar ve sonucu ana programa döndürür. sqrt() veya sin() gibi aritmetik fonksiyonlar bunlara örnektir.

    Ikinci tip fonksiyonlar kendilerine verilen bilgiyi degerlendirir ve bu bilgi sonucunda yapilan islemin basariyla mi basarisizlika mi sonuçlandigini döndürür. Dosya üzerinde islem yapan fclose() fonksiyonu bu tip fonksiyonlara bir örnektir. Parametre olarak verilen dosya düzgün kapatilabilirse 0, aksi halde EOF döndürür.

    Son fonksiyon tipi, herhangi bir dönüs degeri olmayan ve tamamen prosedürel yapida çalisan fonksiyonlari içerir. Bu tip fonksiyonlar çagirildiktan sonra, tanimli olan islem kümesini gerçeklestirir ve ana programa dönerler.

    Deger döndüren fonksiyonlarda, Pascal’da oldugu gibi, dönüs degerini herhangi bri degiskene atama zorunlulugu yoktur. Fonksiyon, degisken kullanmadan da, bir islemin sonucunu veya direkt oalrak bir degeri kullanarak, programa deger döndürebilir. Örnegin;

    int mul(int a, int b)
      {
      return a*b;
      }
      int main(void)
      {
      int x, y, z;
      x = 10; y = 20;
      z = mul(x, y); /* 1 */
      printf(”%d”, mul(x,y)); /* 2 */
      mul(x, y); /* 3 */
      return 0;
      }

    Bu programda mul() fonksiyonu, verilen 2 parametrenin çarpim sonucunu, yedek bir degisken kullanmadan döndürmektedir.

    6.5.3 Pointer döndürme

    Pointer döndüren fonksiyonlar, diger veri tipleridne deger döndüren fonksiyonlarla ayni görevi yaparlar. Bu tip fonksiyonlari tanimalrken dikkat edilmesi gereken sey döencek pointer’in ne tip bir degiskeni gösterdigi bilgisidir. Çünkü dönüs degeri aritmetik islemde kullanildiginda tipi sorun çikartabilir. Bazi durumlarda, hangi tip pointer dönecegi bilinmediginden, genel pointer tipi olan void * kullanilabilir.

    #include
    char *match(char c, char *s)
      {
      while(c!=*s && *s) s++;
      return(s);
      }
      void main(void)
      {
      char s[80], *p, ch;
      gets(s);
      ch = getchar();
      p = match(ch, s);
      if(*p) /* there is a match */
      printf(”%s “, p);
      else
      printf(”No match found.”);
      }

    6.5.4 void tipinde fonksiyonlar

    void veri tipinin kullanim alanlarindan biri, herhangi bir deger döndürmeyen fonksiyonlarin dönüs tipi olarak kullanilmasidir. Bu tip fonksiyonlar prosedürel fonksiyonlardir. Örnegin;

    #include
    void print_vertical(char *str)
      {
      while(*str)
      printf(”%cn”, *str++);
      }
    void main(int argc, char *argv[])
      {
      if(argc > 1) print_vertical(argv[1]);
      }

    programindaki print_vertical() fonksiyonu, verilen bir stringin her karakterini bir satira yazar ve ana programa döner. Herhangi bir dönüs degeri yoktur.

    6.6 main() fonksiyonu

    C, fonksiyon temelli bir programlama dili oldugundan, bir programin ana fonksiyonu olarak main() tanimlanir. main() in dönüs tipi, gelistirme platformuna göre degisir. Çogu C compiler’i main’in default dönüs ipini void olarak kabul ederken, UNIX’te main dönüs tipi int’tir.

    6.7 Fonksiyon prototipleri

    C’de fonksiyon kodu yazilamdan önce fonksiyona ait prototip yazilmali ve fonksiyon tanimlanmalidir. Bu teknik olarak gerekli olmasa da kullanimi genelde desteklenmektedir. Prototip kullanimi fonksiyona tip kontrolünde kolaylik saglamaktadir. Prototip kullanimi ayrica derleyiciye argüman sayisini ve tipini farkli noktalarda kontrol etme imkani da saglar. Fonksiyon prototipinin genel yazimi;

    dtipi fonk_adi (argüman listesi);

    Argüman listesinde argümanlarin isimlerini kullanma zorunlulugu yoktur. Fakat veri tiplerini verem zorunlulugu vardir. Asagidaki kod örnegi, prototip kullanmanin gerekliligini gösterir. sqr_it() fonksiyonu int * yerine int ile çagrilmaya çalisildigindan, derleyici programin çalismasindan önce derleme aninda hata verecektir;

    void sqr_it(int *i); /* prototype */
    int main(void)
      {
      int x;
      x = 10;
      sqr_it(x); /* type mismatch */
      return 0;
      }
    void sqr_it(int *i)
      {
      *i = *i * *i;
      }

    Etiketler: , , , ,

  • 22Nis

    Pointer nedir?

    Pointer, hafizada baska bir adrese ait degeri tutan - baska bir adresi gösteren degiskene denir. Örnegin;

    1000 1003
    1001
    1002
    1003
    1004
    1005
    1006

    C’de pointer kullanimi oldukça önemlidir. Herhangi bir pointer’in yanlis kullanimi programinizin yanlis çalismasina veya büyük ihtimalle ‘patlamasi’na yol açar ve buna yol açan pointer hatasini bulmak da bir o kadar zordur.

    Pointer tipinde degiskenin tanimlanmasinda önce degiskenin ne tip bir degeri gösterdigini tanimlamak gerekir. Bunun yaninda pointer tipi degiskenler her zaman * isareti ile kullanilir:

    veritipi *d_adi;

    veritipi d_adi adli pointer’in hafizada gösterdigi adreste ne tip bir degisken oldugunu belirtir. Teknik olarak herhangi bir pointer hafizada herhangi tipte bir degiskeni gösterebilir. Ama pointerlar ile yapilan islemlerde gösterdigi veritipi gözönüne alinarak hesap yapildigindan veritipi önem kazanir.

    Pointer islemlerinde 2 ayri operatör kullanilir. Bunlardan biri degiskenin bir adres bilgisi tuttugunu gösteren ve o adresteki degeri veren *, digeri de degiskenin hafizadaki adresini gösteren & operatörüdür. Örnegin;

    m = &count;

    kodu m degiskenine count’un adresini yazar. Bu islemin count’un degeri ile hiç bir isi yoktur. Yaptigi tek sey count degiskeninin tutuldugu adresi alip m degiskenine atamaktir. Bunun yaninda;

    n = *m;

    kodu da m adresinde tutulan degiskenin degerini alir ve n’e atar. Bir önceki kod ile bu kod beraber düsünülürse birincisi count’un adresini m’e atiyor, ikincisi de m adresindeki degeri, yani count’un tutuldugu adresteki degeri, yani count’un degerini n’e atiyor.

    5.2 Pointer islemleri

    5.2.1 Pointer atamalari

    Pointer ifadelerinin kullanildigi örnek bir kod yazarsak;

    int x = 99;
    int *p1, *p2;
    p1 = &x;
    p2 = p1;
    printf(“p1 ve p2 adreslerindeki degerler %d ve %d dir.n”, *p1, *p2);
    printf(“p1 ve p2 adreslerinin degerleri %p ve %p dir.n”, p1, p2);

      
    Görüldügü gibi pointer tipindeki degiskenler, ayni tipte veriyi gösteriyorlarsa kendi aralarinda atama islemi yapilabilir.

    Bu programda dikkat çekecek baska bir nokta da pointer tipindeki degiskenleri yazdirirken kullanilan %p elemanidir. Pointerlar nümerik içerik tutmalarina ragmen %p ile yazdirilir. Aslinda bu sayiyi %X, yani 16lik tabanda, yazdirma islemi ile aynidir.

    5.2.2 Pointer tip çevrimleri

    Bir önceki örnekte ayni tip veriyi gösteren pointerlar birbirine esitlenebiliyordu. Farkli tip veri gösteren pointerlar da bu tip bir isleme sokulabilir ama bunun için tip çevrimi yapilmasi gerekir. Bunun iki yolu vardir: void * tipinde bir pointer kullanarak veya kullanmayarak.

    void * tipinde bir pointer C’de genel tipte bir pointer olarak kullanilir. Yani baska tipteki bri pointer’a void tipindeki bir pointer’in degerini veya void * tipindeki bir pointera herhangi bir tipteki bir pointer’in degerini atayabiliriz.

    void * kullanamadan veri tipi çevirimi yapmak istenirse daha önce de kullanilan casr operatörleri kullanilir. Fakat veri tiplerine bagli olarak yapilan çevrim islemi farkli sonuçlar dogurabilir. Örnegin;

    double x = 100.1, y;
    int *p;
    p = (int *)&x;
    y = *p;

    kod parçasini test ettigimizde y’nin 100.1 degeri yerine 26214 degerini aldigini görürüz. Bunun sebebi pointer islemlerinin gösterdigi veri tipinin baz alinarak yapilmis olmasidir. Double 8-byte, integer da 2-byte oldugundan, yazilan atamalarda sorun olmamasina ragmen yanlis sonus elde edilmistir.

    5.2.3 Pointer aritmetigi

    Pointer üzerinde yapilabilecek iki tip aritmetik islem vardir: Toplama ve çikarma. Bu islemlerin pointerlar üzerinde nasil degisiklik yaptigi görmek istenirse: p1’in 2000 adresi ve int tipinde deger gösterdigi varsayilirsa;

    p1++;

    sonucunda p1’in alacagi deger 2001 degil 2002’dir. Bunun sebebi de p1’in 2-byte’lik int tipinde degisken göstermesidir. Ayni sekilde;

    p1–;

    islemi sonrasinda p1 1998 adres degerini içerir. Burdan bir pointer’in her artirildiginda, hafizada ayni tipteki bir sonraki degeri, azaltildginda da hafizada ayni tipteki bir önceki degeri gösterdigi sonucuna varilir. Bunun yaninda pointerlar ile tamsayi degerleri kullanilarak da islem yapilabilir. Örnegin;

    p1 = p1 + 12;

    sonucunda p1, ilk degerden sonraki ayni tipteki 12. degeri göstermektedir. Son olarak da iki pointer’in farkinin alinmasi islemine izin verilmistir. Bunun sebebi de iki adres arasindaki farki bulup, o tipteki eleman sayisinin hesaplanmasi islemini kolaylastirmaktir.

    5.2.4 Pointer karsilastirmalari

    Pointerlar da diger degiskenler gibi baginti operatörleri ile kosullarda kullanilabilir. Örnegin;

    if (p < q) printf(“p daha dusuk bir hafiza adresini gostermektedir”);

    Pointerlar arasi karsilastirmalar genelde pointerlar ayni yapi içerisinde hafiza adreslerini, örnegin bir dizi, gösteriyorsa kullanilir.

    5.3 Pointerlar ve diziler

    Diziler ve pointerlar arasinda yakin bir iliski vardir. Örnegin;

    char str[80], *p1;
    p1 = str;

    Burada p1, str dizisinin - stringinin - ilk elamaninin adresinin degerini alir. Yani string adi, aslinda o stringin hafizadaki baslangiç adresini = stringin ilk karakterinin adresini tutmaktadir. str dizisinin 5. elemanina erismek için ise;

    str[4] veya *(p1+4)

    ifadelerini kullaniriz. Her ikisinin de anlami aynidir.

    C’de dizi elemanlarina 2 sekilde ulasilir: pointer kullanimi ile ve indis kullanimi ile. Indis kullanimi gelistirme ve anlama bakimindan bir kolaylik saglasa da, hiz önemli bir konu oldugundan C programcilari genelde dizi erisimini pointer kullanarak yaparlar. Asagida ayni isi yapan iki fonksiyon yeralmaktadir:

    void putstr(char *s)
      {
      int t;
       for (t=0; s[t]; ++t) putchar(s[t]);
       }
        void putstr(char *s)
       {
      while (*s) putchar(*s++);
      }

    Çogu profesyonel C programcisi pointer kullanilan versiyonu kullanmayi tercih eder.

    5.3.1 Pointer dizileri

    Pointer tipi degiskenler de tüm diger tipler gibi bir dizide saklanabilir. Tanimlamasi;

    veritipi *pdadi[boyut];

    Bu tanimlama veritipi tipinde boyut kadar degeri gösteren, pdadi adinda bir adres dizisini tanimlar. Bu diznin elemanlari üzerinde yapilacak islemler normal pointer degiskenleri ile yapilacak islemler ile aynidir. Örnegin;

    int *x[10];
    x[2] = &var;

    10 elemanli, int tipinde degiskenler gösteren bir pointer dizisi tanimlar ve bu dizinin üçüncü gözüne var adli degiskenin adresini atar. var degikeninin degeri için yazacagimiz ifade ise;

    *x[2] dir.

    Pointer dizileri genedelde string gösteren pointerlar tutmak için kullanilir.

    5.4 Pointer gösteren pointerlar

    Tipki diger veri tiplerini gösteren pointerlar gibi pointerlari gösteren pointerlar da mevcuttur. Bu yapida tanimlanan pointer, esas degerin blundugu adres degerini tutan adresi belirtir. Yani;

    Pointeri baska bir pointer kullanarak gösterme islemine multiple-direction adi verilir. Pointer gösteren pointer tanimi ise;

    veritipi **ppadi;
    seklindedir. Örnegin;
    float **balance;

    tanimlamasi float tipinde deger içeren adresi içeren degiskenin adresini gösteren degiskeni tanimlar.

    void main(void)
      {
      int x, *p, **q;
      x = 10;
      p = &x;
      q = &p;
      printf(“x in degeri %dn”, **q);
      }

    Etiketler: , , , ,

« nceki Sayfa   

site ekle | site dizin | pr ler | pr l | pagerank lme