|  | 
        
            | 
                    
                        | Fonksiyon Göstericileri ve Uygulamaları |  |  
                        | 
	
    
		
            | Gönderiliyor lütfen bekleyin... | 
 |  | 
        
            | C dilinde yazdığımız br fonksiyonu çağırdığımızda 
şimdilik neler  olup bittiğini tam olarak bilmesek de bildiğimiz bir şey 
var ki; o da fonksiyonlara ait kodların da bellekte tutulmasıdır. 
Fonksiyonlarda normal veri tipleri gibi bellekte bulunurlar ve bellekte bulunduğu 
bölgenin başlangıç adresi mevcuttur. Bu makalemizde fonksiyon göstericilerini 
tanımlama, fonksyion göstericilerinin uygulama alanlarını ve basit bir "Komut Yorumlayıcı"  programıyla 
fonksyion göstericilerinin kullanımını göreceğiz.  
Aşağıdaki kod parçasında 
  olan bitene bir göz atalım; 
 int 
  islev()
 {
 int x;
 x=
   2 ;
 return x;
 }
 int main(void)
 {
 int y ;
 y=islev();
 return 0;
 }
 
 Programımızın akışı main işlevi içinde y=  
   islev(); satırına geldiğindemain işlevinin akışı durdurulur ve "islev" fonksiyonunun 
  bulunduğu adrese gidilir, ve o adresten işlemler yapılmaya devam edilir.İşlev 
  fonksiyonu icra edildikten sonra main işlevi kaldığı yerden devam ediyor. 
  Evet gördüğünüz gibi her şey bildiğimiz gibi normal bir şekilde işledi. 
  Peki bu mekanizma nasıl işledi? Main işlevi içinden islev() fonksiyonuna nasıl 
  atladık?Bütün bunların cevabı fonksiyon göstericileridir, şöyle ki, 
  aslında biz farkına varmasak da y=islev(); dediğimizde "islev" 
  adresindeki kodu icra etmek istediğimizi bildiriyoruz. Kısacası bir fonksiyonun 
  ismi o fonksiyonun kodlarının bulunduğu bellek bölgesinin başlangıç adresidir."islev" 
  bir adres "()" ise fonksiyon çağırma operatörüdür.Fonksiyon çağırma 
  operatörü fonksiyonun geri dönüş değerini üretir.
 
 islev=> geri 
  dönüş değeri int türünden olan bir fonksiyonun adresini tutan sabit bir bilgidir.
 
 Fonksiyon göstericileri de 
  bir nesne olduğuna göre tanımlanmaları ve onlara değer atamak son derece legal 
  bir durumdur. Mesela bir fonksiyonun başlangıç adresi, bir fonksiyon göstericisine 
  atanabilir.
 Bir fonksiyon gösterici aşağıdaki gibi tanımlanır:
 
 <geri 
  dönüş değeri türü> (* gösterici ismi)([parametreler])
 
 Aşağıda tanımlamaları 
  verilmiş fonksiyon göstericilerini dikkatlice izleyin.
 
 int 
  (*p)(void);
 void (*t)(int t,int m);
 void (*k)(void);
 
 Bir fonksiyon göstericisine 
  her tür fonksiyon göstericisi atayamayız. Değerini atadığımız fonksiyon göstericisinin 
  adresini tuttuğu fonksiyonun parametrik yapısı ve geri dönüş değeri, atama yapılacak 
  göstericinin türüne uygun olmalıdır. Mesela yukarıda tanımlanan p fonksiyon 
  göstericisine ancak ve ancak geri dönüş değeri int ve parametresi olmayan bir 
  fonksiyonun adresi atanabilir.Aşağıdaki atamaların tamamı yanlış ve geçersiz 
  atamalardır.
 
 p=t; 
  t=k; k=p; // yanlış
 
 Fonksiyon gösterici 
  tanımlarken kullandığımız ilk parantezler mutlaka kullanılmalıdır.Aksi halde 
  tanımlamamız anlam değiştirip fonksiyon prototip tanımlamasına dönecektir. Aşağıda 
  bu iki duruma örnek verilmiştir.
 
 void 
  (*pFunc)(int,int) 
  // pFunc, geri dönüş değeri void ve parametrik yapısı 
  int,int olan bir fonksiyon gösterici türüdür.
 
 void 
  *pFunc(int,int) 
  // pFunc, geri dönüş değeri void türden bir gösterici 
  olan ve parametrik yapısı int,int olan bir fonksiyon adıdır.Ve aynı zamanda 
  bir adres sabitidir.
 
 C dilinde fonksiyon 
  isimleri tıpkı dizi isimlerinde olduğu gibi fonksiyonların bellekteki adres 
  bilgilerini tutar ve bir sabit olarak ele alınırlar. Fonksiyon isimleri nesne 
  olmadıkları için onlara herhangi bir fonksiyon göstericisinin değeri atanamaz.Aşağıdaki 
  örnekte basit bir fonksiyon göstericisi kullanımı göreceksiniz.
 
 void 
  func(int a,int b)
 {
 printf("Ben adım func\n");
 }
 
 int 
  main(void)
 {
 void (*pFunc)(int,int); // funcın adresini atamak için 
  bir gösterici tanımlıyoruz.
 pFunc=func(); // uygun bir gösterici ataması yaptık.
 return 0;
 }
 
 Fonksiyon göstericisi ile 
  fonksiyon çağırma, () operatörü ile yapılır. Bu durumda () operatörünün operandı 
  fonksiyon adresi olabileceği gibi bir fonksiyon göstericisi de olabilmektedir.Operand 
  fonksiyon göstericisi olması durumunda programın akışı gösterici içindeki adrese 
  gidecektir. Fonksiyon göstericiler de diğer türler gibi fonksiyonlara paremetre 
  olarak geçirilebilirler.Mesela aşağıdaki "func" fonksiyonu parametresi 
  bir fonksiyon gösterici olan fonksiyondur.
 
 void 
  normalfunc(void)
 {
 printf("Normal Fonksiyon");
 }
 
 void 
  func(void (*p)(void))
 {
 p();
 }
 
 int 
  main(void)
 {
 func(normalfunc);
 return 0;
 }
 
 Yukarıdaki kodda 
  main işlevi içinde "func" fonksiyonuna "normalfunc" fonksiyonunun 
  adresi geçiliyor ve "func" da kendisine gelen adresteki koda akışı 
  sağlıyor.Bu kodda fonksiyonların çağrılma sırası aşağıdaki gibi olacaktır.
 
 main() 
  -> func() -> normalfunc() -> main()
 
 Fonksiyon göstericileri 
  genellikle, bir fonksiyonun parametresi olarak kullnanılırlar.Bu şekilde ana fonksiyonun 
  işlevi genelleştirilerek belli durumlarda parametre olarak aldığı fonksiyon 
  göstericisinin tutuğu adresteki fonksiyonu çalıştırır.Bu şekilde ana fonksiyonu 
  hiç değiştirmeksizin programımıza yeni modüller ekleyebiliriz.Makalemizin sonunda 
  fonksiyon göstericilerinin bu şekilde kullanımına örnek olması için basit bir 
  komut yorumlayıcısı yazacağız.
 
 Önemli Not:void 
  (*p)(); ifadesinde pye geri dönüş değeri void olan ve herhangi bir paremetrik 
  yapıya sahip olan fonksiyon gösterici atanabilir. void (*p)(void); ifadesindeki 
  p ye ise sadece geri dönüş değeri void ve parametresi void olan bir fonksiyon 
  göstericisi atanabilir.
 
 Fonksiyon göstericilerininde 
  diğer türler gibi dizileri olabilir.Mesela void (*a[10])(void); tanımlaması 
  a nın ,10 elamanlı bir fonksiyon gösterici dizisi olduğunu gösterir.Bu tür tanımlamalar 
  okunabilirliği zorlaştırdığı için typedef edilmesi okunabilirlik açısından daha 
  uygun olabilir.Örneğin;
 
 typedef 
  void (*pF)(void);
 pF p; ile void (*p)(void); // yukarıdaki typedef işleminden 
  sonra bu iki tanımlama aynı anlama gelir.
 
 Buna benzer olarak,
 
 typedef 
  void (*a[10])(void); // burda a 10 elemanlı fonksiyon 
  gösterici dizisidir.
 
 Normal türler de 
  olduğu gibi fonksiyon göstericilerine de tür dönüştürme işlemi ugulanabilir. 
  Mesela,
 
 int 
  func(void)
 {
 ...
 }
 int (*p)(int,int);
 p=func; //hata
 p=( int(*)(int,int) ) func; //yukarıdaki hata tür dönüştürme 
  ile legal getirilebilir. En dıştaki parantezler tür dönüştürme operatörüdür.
 
 Uygulama
 
 Fonksiyon göstericilerine 
  örnek olması açısından aşağıdaki basit komut yorumlayıcısını inceleyelim.Bir 
  prompt çıkararak kullanıcıdan komutlar alarak bunları yorumlayıp çeşitli işlemler 
  yapan programlara "komut yorumlayıcısı" denir.Komut yorumlayıcı programların 
  algoritması bir döngü içinde bir string almak, bunu komut listesinde taramak 
  ve uygun işlemleri yapmaktır.Bu tür prgramlar genellikle fonksiyon göstericileri 
  kullanırlar.Biz bu uygulamamızda komut yorumlayıcısının ana çatısını yazacağız 
  fakat komutların anlamsal işlevlerini yapmak başka derslerin konusu olduğu için 
  komutların işlevi boş bırakılacaktır.
 
 #include 
  <stdio.h>
 #define CMD_SIZE 120
 
 //Aşağıdaki 
  komut yapısında, her komut için bir ad, ve her komutun yapılması için o komuta 
  ait fonksiyonun adresi tutulur
 
 typedef 
  struct _KOMUT{
 char *komutAdi;
 void (*proc)(void);
 }KOMUT;
 
 //Komutlarımız.Dikkat 
  ederseniz bütün fonksiyonların parametrik yapısı ve geri dönüş değeri özdeştir.
 
 void 
  Edit(void)
 {
 printf("Edit\n");
 }
 
 
 void Copy(void)
 {
 printf("Copy\n");
 }
 
 
 void Format(void)
 {
 printf("Format\n");
 }
 
 
 void Dir(Exit)
 {
 printf("Exit\n");
 }
 
 //KOMUT 
  yapısı türünde bir global dizi oluşturup komutlarımızın adlarını ve komutlara 
  ait fonksiyonları yerleştirelim
 
 KOMUT 
  komutlarim[]={ {"Edit",Edit},{"copy",Copy},{"Format",Format},{"exit",Exit} 
  } ;
 
 
 //Ana işlevimiz
 
 
 
 int 
  main()void
 {
 char KOMUTADI[CMD_SIZE];
 int i;
 
 for(; ;){
 printf("CS>");
 gets(KOMUTADI);
 for (i=0 ; komutlarim[i].komutAdi !=NULL ; ++i)
 if(!(strcmp(KOMUTADI,komutlarim[i].komutAdi))){
 komutlarim[i].proc();
 break;
 }
 if (komutlarim[i].komutAdi ==
    
     NULL)
 printf("Komut bulunmadı:\n") ;
 }
 return 0;
 }
 
 
 
                Makale:Fonksiyon Göstericileri ve Uygulamaları C ve Sistem Programlama Sefer Algan
 | 
        
            |  | 
        
            |  | 
        
            | 
                    
                        
                            
                        
                            Eklenen Son 10 
                            Bu Konuda Geçmiş 10 
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                            Son Eklenen 10 Makale Yükleniyor
                         
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         | 
        
            |  |