ELN1001 BİLGİSAYAR PROGRAMLAMA I DEPOLAMA SINIFLARI DEĞİŞKEN MENZİLLERİ YİNELEMELİ FONKSİYONLAR Depolama Sınıfları Tanıtıcılar için şu ana kadar görülmüş olan özellikler: Ad Tip Boyut Değer Bunlara ilave olarak Depolama Sınıfı Depolama Süresi Menzil Bağlanım 1
Depolama Sınıfları Depolama sınıfı kendi depolama süresi, menzil ve bağlanımını da belirler Depolama süresi, tanıtıcının bellekte kalacağı süreyi belirler. Bu tanıtıcıların bazıları açık şekilde tanıtılır, bazıları oluşturulur yok edilir daha sonra yeniden oluşturulur ve bu şekilde devam eder. Bazıları ise programın başından sonuna kadar bellekte yer alır. Menzil tanıtıcının programın nerelerinde kullanılabilir olduğunu belirleyen bir özelliktir. Bazıları programın belirli kısımlarında kullanılırken, bazıları programın tamamı için geçerli olabilmektedir. Bağlanım, birden fazla kaynak dosyaya sahip bir programda, gerekli bildirimler yapıldığı takdirde tanıtıcının hangi kaynak dosyalar tarafından kullanılabilir olduğunu belirleyen bir özelliktir. Depolama Sınıfları C programlama dilinde iki ayrı kısımda dört farklı depolama sınıfı mevcuttur. Otomatik Depolama Süresi Auto Register Statik Depolama Süresi Extern Static 2
Depolama Sınıfları Otomatik Depolama Süresi Auto ve Register anahtar kelimeleri otomatik depolama süresi için kullanılmaktadır. Otomatik depolama süresine sahip değişkenler tanımlandıkları blok çağrıldığı zaman oluşturulur, blok aktif olduğu sürece var olur ve bloktan çıkıldığı anda bellekten silinirler. Yalnızca değişkenler otomatik depolama süresine sahip olabilir. Bir fonksiyonun lokal değişkenleri normalde otomatik depolama süresine sahiptir. Depolama Sınıfları Otomatik Depolama Süresi Auto anahtar kelimesi adından da anlaşılabileceği gibi açıkça değişkenlerin otomatik depolama süresine sahip olduğunu belirtir. Örneğin auto double x,y; ifadesindeki değişkenler otomatik yerel değişkenlerdir ve yalnızca değişkenlerin yer aldığı fonksiyon gövdesi için kullanılabilirlerdir. Yerel değişkenler varsayılan olarak zaten otomatik depolama süresine sahiptir, bu yüzden auto anahtar kelimesi çok nadir kullanılır. Otomatik depolama süresine sahip değişkenler otomatik değişkenler olarak adlandırılırlar. 3
Depolama Sınıfları Otomatik Depolama Süresi Otomatik depolama süresi bir anlamda bellekten tasarruf sağlamaktadır, çünkü yalnızca ihtiyaç duydukları durumlarda var olmaktadırlar. İçinde tanımlı oldukları fonksiyonun bir üst fonksiyon tarafından çağrılmasıyla oluşturulurlar ve fonksiyondan çıkıldığı zaman yok edilirler. Depolama Sınıfları Otomatik Depolama Süresi register anahtar kelimesi kullanıldığında, otomatik değişken bilgisayar işlemcisinin kendi saklayıcılarından birisine yerleştirilir. Dikkatli bir kullanımla, değişkenleri yerleştirmek için RAM e erişim gerektirmediği için, performans konusunda önemli bir katkı sağlayacaktır. Derleyici, register anahtar kelimesini göz ardı edebilir. Örneğin, işlemci yoğun kullanılıyorsa ve saklayıcıları uygun değilse programda böyle bir yerleşim gerektirmez. register int sayac=1; Çoğunlukla, register bildirimleri gereksizdir. Günümüzün modern derleyicileri, sık kullanılan değişkenleri fark ederek, ayrıca bir register bildirimine ihtiyaç duymadan değişkenleri işlemci saklayıcılarına yerleştirirler. Register anahtar kelimesi yalnızca otomatik değişkenlerle kullanılabilir. 4
Depolama Sınıfları Statik Depolama Süresi extern ve statik anahtar kelimeleri değişken ve fonksiyon tanıtıcılarının statik depolama süresine sahip olduğunu bildirirler. Statik depolama süresine sahip değişkenler program başlar başlamaz oluşturulurlar ve program boyunca var olurlar. Statik değişkenler için program başlangıcında yer tahsisi ve ilk değer ataması gerçekleştirilir. Fonksiyonlar için, program başlarken fonksiyon adı tanıtılır ve program boyunca fonksiyon var olur. Bununla birlikte, değişkenler ve fonksiyon adlarının programın başından sonuna kadar var olması demek bu değişken veya fonksiyonlara programın her noktasından erişilebilir olması anlamına gelmez. Depolama süresi ve menzil farklı kavramlardır. Depolama Sınıfları Statik Depolama Süresi Statik depolama süresine sahip iki ayrı bildirim tipi mevcuttur: extern: global değişkenler ve fonksiyon isimleri Statik: lokal değişkenler Global değişkenler ve fonksiyon isimleri için varsayılan bildirim tipi extern dir. Global değişkenler, tüm fonksiyon bloklarının dışında yer ve varlığını programın başından sonuna kadar korur. Global değişken ve fonksiyonlar kaynak kodu içerisinde kendi bildirim veya tanımlamalarını takip eden tüm kod blokları tarafından kullanılabilirdir. Bu fonksiyon prototipi kullanmanın sebeplerinden birisidir; örneğin printf çağıran bir programın içine <stdio.h> yerleştirdiğimizde, fonksiyon prototipi kaynak kodumuzun başına yerleştirilerek, printf fonksiyonunun kendisini takip eden kod satırları tarafından kullanılabilir olmasını sağlar. 5
Depolama Sınıfları Statik Depolama Süresi Bir değişkeni global olarak tanımlamanın bazı yan etkileri oluşur; örneğin bir değişkene erişmesi gerekmediği halde bir fonksiyon içinden yanlışlıkla o değişkene erişilir ve değişiklik yapılabilir, bu da programda mantık hatasının oluşmasına yol açar. Bu yüzden, fonksiyonların kendi çalışması için ihtiyaç duyduğu değişkenler lokal değişkenlerdir. Depolama Sınıfları Statik Depolama Süresi static anahtar kelimesi ile kullanılan yerel değişkenler yalnızca tanımlandıkları fonksiyon tarafından bilinir durumdadırlar, fakat otomatik değişkenlerin tersine, statik yerel değişkenler fonksiyondan çıkılsa bile RAM de kendileri tahsis edilen yeri korumaktadırlar. Fonksiyonun bir sonraki çağrılışında, içlerinde bulunan değerler, fonksiyondan en son çıkışlarında içlerinde kalan değerdir. Aşağıdaki bildirim sayac adlı bir statik değişken tanımlamakta ve ilk değerini 1 yapmaktadır. static int sayac=1; Statik depolama süresine sahip tüm sayısal değerler, bir ilk değer ataması yapılmaması durumunda, derleyici tarafından otomatik olarak sıfır ilk değerine atanırlar. 6
Menzil Menzil, tanıtıcının programın hangi parçaları tarafından kullanılabilir olduğunu belirleyen bir kavramdır. Örneğin, bir blok içinde lokal bir değişken tanımlanırsa, değişken kendisini takip eden kod bloğu tarafından kullanılabilirdir. Dört tanıtıcı menzili tipi vardır: Fonksiyon menzili Dosya menzili Blok menzili Fonksiyon prototipi menzili Menzil Etiketler (tanıtıcının ardından iki nokta gelir, devam_et: gibi ), fonksiyon menziline sahip tanıtıcılardır. Tanımlandıkları fonksiyonun herhangi bir noktasından erişilebilirler, fakat fonksiyon dışından erişilemezler. Örneğin: switch case ifadesi goto ifadesi Değişkenler fonksiyonların birbirlerinden gizledikleri gerçekleme detaylarıdır. Bu gizleme bilgi gizleme diğer fonksiyonların bu bilgiye sahip olmaları gerekmediğinden, programcılık açısından faydalıdır. Fonksiyonlar dışında tanımlanmış tanıtıcılar dosya menziline sahiptir. Bu tip bir tanıtıcı, tanıtıldığı noktadan dosyanın sonuna kadar olan tüm fonksiyonlar tarafından kullanılabilir durumdadır. Global değişkenleri fonksiyon tanımlamaları, fonksiyon prototipleri fonksiyon dışında tanımlandıklarından dosya menziline sahiplerdir. 7
Menzil Bir blok içinde tanımlanan tanıtıcılar blok menziline sahiptirler. Blok menzili, bloğu sonlandıran sağ küme parantezi (}) ile sona erer. Fonksiyonların başında tanıtılmış lokal değişkenler, fonksiyon değişkenleri olarak blok menziline sahiplerdir. Herhangi bir blok, değişken tanımlamalarını içerebilir. İç içe bloklar oluşturulduğu zaman, ve dış blokta tanımlanmış bir değişkenle aynı ada sahip bir değişken içi blokta da tanımlandıysa, iç blok sona erene kadar dış bloktaki değişken gizlenir. Bunun anlamı, iç bloktaki operasyon devam ederken, değişkeni kullanmak gerektiğinde, bloktaki fonksiyonların yalnızca kendi iç değişkenlerini görebildiğidir. statik ile tanımlanmış yerel değişkenler de, programın başından sonuna kadar var olmalarına rağmen blok menziline sahip olacaklardır. Dolayısıyla, menzil ile depolama süresi birbirlerinden farklı kavramlardır. Menzil Bir fonksiyon prototipinin değişken listesinde kullanılan değişkenler, fonksiyon prototipi menziline sahiptirler. Daha önceden de bahsedildiği gibi, fonksiyon prototipleri değişken listelerinde değişken isimlerine ihtiyaç duymazlar, yalnızca tipleri gereklidir. Eğer değişken listesinde isim kullanılırsa, derleyici bu isimleri göz ardı eder. Fonksiyon prototipinde kullanılan tanıtıcılar programın herhangi başka bir noktasında hiçbir karışıklık oluşturmadan yeniden kullanılabilirler. 8
Örnek: Menzil Yineleme (Recursion) Yinelemeli (Recursive) Fonksiyonlar Şu ana kadar gördüğümüz kısımlarda, disiplinli, hiyerarşik bir anlamda bir fonksiyonun diğer bir fonksiyonu çağırdığı genel yapılar üzerinde duruldu. Bazı tip problemlerde, fonksiyonların kendi kendilerini çağırması oldukça faydalıdır. Yinelemeli (recursive-rekürsif) fonksiyon kendisini ya doğrudan veya başka bir fonksiyon aracılığıyla dolaylı olarak çağıran fonksiyonlara verilen isimdir. Yinelemeli fonksiyonlar, üst düzey programlamacılıkta kullanılan ve halen yoğun şekilde araştırmalara konu olan bir başlıktır. Bu bölümde, yinelemeyle ilgili basit örnekler tanıtılacaktır. 9
Yineleme Öncelikle yineleme kavramı üzerinde düşünülmeli, daha sonra yinelemeli fonksiyonlar içeren temel programlar incelenmelidir. Yinelemeli problem çözme yaklaşımları bilinen birkaç elemana sahiptir. Yinelemeli fonksiyon bir problemi çözmek için çağırılır. Fonksiyon aslında, yalnızca en basit durumu, veya diğer adıyla temel durumu çözmeyi bilmektedir. Eğer temel durumla birlikte bir fonksiyon çağırılırsa, fonksiyon cevap olarak bir sonuç döndürür. Eğer fonksiyon daha karmaşık bir problem için çağırılırsa, fonksiyon problemi iki kavramsal parçaya böler: Nasıl çözüme ulaşacağını bilen parça Nasıl çözüme ulaşacağını bilmeyen parça Yinelemenin uygulanabilir olması için, sonraki parça orijinal probleme benzemelidir, fakat daha basit ve daha küçük bir versiyonu olmalıdır. Yineleme Bu yeni problem, orijinal probleme benzediği için, fonksiyon, belleğe bu yeni problemin üzerinde çalışması için yeni bir kopyasını açar, buna yinelemeli çağrı adı verilir, ayrıca yineleme adımı olarak da adlandırılır. Yineleme adımı, return anahtar kelimesini içerir, çünkü döndüreceği sonuç orijinal çağırıcıya (örn. main) döndürülecek sonucu oluşturacak problem parçasını nasıl çözeceğini bilen fonksiyon ile birleştirilecektir. Yineleme adımı, fonksiyona yapılmış orijinal çağrı halen açıkken çalıştırılır, yani orijinal fonksiyon çalışmasını henüz tamamlamamıştır. Yineleme adımı, fonksiyonun kendisine ulaşan problemi iki kavramsal parçaya ayırmayı devam ettirdiği sürece, daha pek çok yineleme çağrısıyla sonuçlanabilir. 10
Yineleme Yinelemenin sona ermesi için, çağırılan fonksiyonun nihai olarak temel duruma erişmesi gerekmektedir. Bu noktada, fonksiyon temel durumu fark eder, bulduğu sonucu kendisini çağıran (yine kendi kopyası olan) fonksiyona döndürür, nihai olarak ilk çağırana erişene (örn. main) kadar bu dizi devam ettirilir. Yinelemeli fonksiyonları oluşturmak büyük dikkat gerektirmektedir. Temel durumu ihmal etmek, veya yineleme adımını yanlış yazmak, yinelemelerin temel duruma erişebilmesini imkansız hale getirir. Bu da belleğin kısa süre içerisinde tükenmesi anlamına gelmektedir. Yinelemeli fonksiyon Pozitif bir tamsayının -n olsun- faktöriyeli: n*(n-1)*(n-2)* *1 çarpımının sonucudur. Yinelemeli olmayan faktöriyel çözümü: factorial=1; for (sayac=girilen_deger;sayac>=1,sayac--) factorial *= sayac; Faktöriyel fonksiyonun yinelemeli tanımı için şu ilişki gözlenebilmelidir. n! = n*(n-1)! 11
Yinelemeli fonksiyon Yineleme Adımları 5! 5*4! 4*3! 3*2! 2*1! 1 Nihai Değer: 120 5! 120 döndürülür 5*4! 24 döndürülür 4*3! 6 döndürülür 3*2! 2 döndürülür 2*1! 1 döndürülür 1 Döndürülen Değerler Faktöriyel Hesaplama 12
Fibonacci Serisi 13