C PROGRAMLAMA
Göstericiler (Pointers) C programlama dilinin en güçlü özelliklerinden biridir. Göstericiler, işaretçiler yada pointer adı da verilmektedir. Gösterici (pointer); içerisinde bellek adresi tutan değişkenlerdir. Şu ana kadar gösterilen tüm değişkenler tanımlandıkları türe göre bir değer saklarlar. Bu değere ulaşılmak istendiğinde doğrudan değişkenin ismi ile erişilebilir. Göstericiler ise değerin bulunduğu bellek hücresinin adresini tutmak sureti ile dolaylı olarak değere erişebilirler.
Neden gösterici (pointer) kullanırız? Fonksiyonlara parametrelerin referansla bağlantılı çağırma (call by reference) yöntemi ile gönderilebilmesi için pointerlar kullanılır. Aksi halde diziler haricindeki bütün parametre aktarımları değerle çağırma yöntemi (call by value) ile yapılacaktır. Devingen veri yapıları (dynamic data structures) oluşturmak ve bunlar üzerinde değişiklik yapmak için pointerlar kullanılır. Bu yapılar; Bağlı listeler (Linked List), Kuyruklar (Queues), Yığıtlar (Stacks), ve Ağaç (Trees) veri yapılarıdır. Bu veri yapıları, dizilerden farklı olarak eleman sayıalrı büyüyebilir ve küçğlebilir. Pointerlar sayesinde belleğin istenilen bir bölgesine erişim yapılabilir.
Göstericilerin (Pointers) tanımlanması ve ilk değer atanması Göstericilerde bir değişkendir, C dilinde değişkenler kullanılmadan önce tanımlanmalıdırlar. Normal değişkenlerden farklı olarak göstericiler aşağıdaki gibi tanımlanmaktadır. Yukarıdaki tanımlamada aptr bir gösterici değişkenidir. İsminin önüne gelen * işareti değişkenin gösterici (pointer) olduğunu ifade eder. aptr pointer integer değişkenin tutulduğu bellek hücresinin adresini tutacaktır. Göstericilere tanımlandıkları anda Ya da daha sonra atama deyimleri ile değer atanabilirler. Bir pointer 0, NULL Ya da herhangi bir bellek adresi olmak üzere üç farklı değer alabilirler. Bir pointerin değerinin 0 sıfır olması NULL olmasıyla aynıdır.
Gösterici Operatörleri & adres operatörü; Tek bir operand alan unary bir operatördür. Önüne yazıldığı operandın bellek adresini üretir. Buradaki operand bir değişken olmalıdır, sabit değerler olamaz. Dolayısıyla bir pointer değişkenine değer atamak için bu operator kullanılır;
& operatörü kullanımı Gösterici Operatörleri
Gösterici Operatörleri * adres operatörü; Türkçe kaynaklarda içerik operatörü Ya da dolaylı adres operatörü olarak geçmektedir. Tek operand alan unary operatördür. Önüne geldiği nesne bir adres Ya da bir adres içeren değişken (pointer değişkeni olmalıdır). Önüne geldiği adresteki değere erişmeyi sağlar. Yukarıdaki örnekte kullandığımız aptr pointer değişkenin işaret ettiği a değişkenine ulaşöak için aşağıdaki komut satırı kullanılır.
Pointer kullanımına örnek; Göstericiler (Pointers)
Göstericiler (Pointers) Fonksiyonları değerle bağlantılı (referansla) çağırma (call by reference); Bu yöntemde, çağıran fonksiyondan gönderilen değerlerin kopyalandığı değişkenlerin değişmesi orijinal değerleri etkiler. Bu yöntem C dilinde ancak pointerler kullanılarak gerçekleştirilir. Fonksiyonlar çıktı olarak geriye tek değer gönderirler. Bazen bir fonksiyondan birden fazla değer üretmesi istenebilir, fakat bu değerlerin hepsini geriye gönderemez, bu durumda fonksiyonları referansla çağırmak iyi bir yöntemdir. Bu işlemi anlatmak için kullanılan en güzel örnek takas (swap) fonksiyonudur. Takas fonksiyonu geriye hiçbir değer döndürmez, sadece kendisine gelen iki değişkenin değerlerini değiştirir.
Göstericiler (Pointers) İlk olarak düz mantıkla yani değerle (call by value) fonksiyon çağırma yöntemine göre deneyelim bakalım fonksiyona gönderdiğimiz değişkenlerin değerlerini değiştirebilecek miyiz. Görüldüğü üzere takas fonksiyonunu değerle çağırdığımızda orijinal değişkenler üzerinde (a,b) hiçbir değişiklik olmadı
Göstericiler (Pointers) Takas fonksiyonunu referansla çağırma yöntemi ile yeniden tasarladığımızda bu işlem hallolacaktır.
const belirleyicisinin pointerlar ile kullanılması Sabit (constant) kelimesinin kısaltılmış halidir. Bu belirleyici ile tanımlanmış değişkenlerin değerleri program içerisinde değiştirilemezler. Bir değişkenin değerinin değiştirilememesinin faydaları şunlardır; Yazılan programın okunabilirliğini artırır. Programı inceleyen başka biri ilk değer ataması yapıldıktan sonra const sabiti ile tanımlanmış bir değişkenin değerinin değiştirilemeyeceğini bilerek kontrol eder. Program yazılırken yanlışlıkla da olsa değişkenin değerinin değiştirilmesini önler.
const belirleyicisinin pointerlar ile kullanılması const belirleyicisi göstericiler ile üç farklı şekilde kullanılır. 1- gösterdiği değerin sabit olması; Göstericinin gösterdiği yer sabittir. Gösterdiği yere erişilip oradaki değer üzerinde değişiklik yapılamaz. Ancak göstericinin tuttuğu adres değiştirilebilir.
const belirleyicisinin pointerlar ile kullanılması 2- göstericinin kendisinin sabit olması; Gösterici değişkeninin kendisi sabittir, yani göstericinin tuttuğu adres bilgisi değiştirilemez. Ancak göstericinin içerisindeki adreste bulunan değer değiştirilebilir.
const belirleyicisinin pointerlar ile kullanılması 3- göstericinin kendisinin ve gösterdiği yerin sabit olması; Göstericinin içerisindeki adres bilgisi ve gösterdiği yer sabittir. İçerisindeki adres değeri ve gösterdiği yerdeki değer değiştirilemez.
sizeof operatörünün kullanılması C programlama dilinde değişken türlerinin ve uzunluklarının ne kadar olduğunu öğrenebilmek için sizeof operatörü kullanılır. Bu bir unary operatördür. Önüne yazıldığı operandın bellekte kapladığı alanın byte cinsinden miktarını verir.
Pointerlar üzerinde aritmetik işlemler Pointerlar aritmetik işlemler için geçerli operandlardır. Ancak taşıdıkları değerler adres olduğundan bütün aritmetik işlemler uygulanamaz. Göstericiler üzerinde yalnızca toplama ve çıkarma işlemleri (+, -, ++, --, +=, -=) uygulanabilir. Burada dikkat edilmesi gereken nokta; bir göstericiden tamsayı çıkartıldığında yada toplandığında içindeki adres gösterdiği türün bellekte kapladığı alan kadar artar yada azalır. aptr değişkenini bir artırmak yada azaltmak demek onu 1*sizeof(long) kadar artırmak yada azaltmak anlamına gelir.
Göstericiler ile diziler arasındaki ilişkiler C dilinde diziler ve göstericiler hemen hemen birbirinin yerlerine kullanılabilirler. Dizi isminin dizinin başlangıç adresinin tuttuğunu hatırlayınız. Dolayısıyla dizinin adı da bir gösterici (pointer) gibi düşünülebilir. Dizilerde dizinin her bir elemanına erişmek için köşeli paranter içinde indis numarası kullanılır. Böyle bir ifadeden derleyici, başlangıç adresinden verilen indis numarası kadar sonraki adreste bulunan elemana gidileceğini anlar. Anlaşılıyor ki derleyici, adres üzerinde artırma ve eksiltme operasyonları ile diğer dizi elamanlarına erişmektedir.
Göstericiler ile diziler arasındaki ilişkileri göstermek için bir örnek;
void Göstericiler Bir gösterici (pointer) içerisindeki adres başka bir gösterici içerisine atanabilir, ancak gösterdikleri türlerin birbirine uygun olması gerekir. Bu kuralın dışında void göstericiler genel gösterici (generic pointer) olarak tanımlanırlar. Herhangi bir göstericinin değeri (yani içindeki adres) void göstericiye atanabilir, tam terside gerçekleşebilir. bu tür göstericiler adreslerin yedeklenmesi yada yer değiştirme işlemleri için kullanılabilirler. Void türü olmayan anlamına geldiğinden herhangi bir değeri referans edemezler, buda onların * ve [ ] gibi operatörler ile kullanılamayacağı anlamına gelir. Aritmetik işlemlerde void göstericiler üzerinde uygulanamaz.
void Göstericiler
fonksiyon Gösterici(pointer to function) Fonksiyonlarda diğer değişkenler ve diziler gibi belleğe yüklenirler. Fonksiyonlarında bir başlangıç adresleri vardır. Dizilerde olduğu gibi fonksiyonun adı da fonksiyonun başlangıç adresini tutar. Bir gösterici yardımıyla bir fonksiyonun adresini tutabilir ve bu gösterici yardımıyla fonksiyonu kullanabiliriz. int topla(int, int); //fonksiyonunu gösteren bir gösterici aşağıdaki gibi tanımlanır. int (*pf)(int, int); Bu gösterici sadece yukarıdaki şekilde tanımlanan fonksiyonları gösterebilir. (İki adet int tipli parametre alan ve geriye int tipli bir değişken döndüren fonksiyonları gösterebilir.
fonksiyon Gösterici(pointer to function)
fonksiyon ların başka fonksiyonlara paremetre olarak gönderilmesi Fonksiyonlar, göstericiler ile temsil edilebildiğinden ve göstericilerde birer değişken olduğundan başka fonksiyonlara parametre olarak gönderilebilirler. Gönderilecek olan fonksiyonda argümanlar fonksiyon işaretçisi şeklinde tanımlanmalıdır.
fonksiyon ların başka fonksiyonlara paremetre olarak gönderilmesi
fonksiyon ların başka fonksiyonlara paremetre olarak gönderilmesi