C Programlama Dilinde İşaretçiler ve Diziler

  • 04-12-2018 10:13
  • 6393

Diziler (Array)

Diziler uzunluğunu bizim belirlediğimiz değişkenlerdir. Tanımlama şekli ise değişken tipi, değişken adı ve köşeli parantezler içinde dizinin eleman sayısı yazılır ya da parantezler boş bırakılarak dizinin içeriği yazılır. Dizinin bütün elemanları tanımda kullanılan değişken ile aynı tiptedir. Örenegin char k[5];  dizisi 5 tane art arda sıralanmış char tipinde değişkendir. Art arda sıralandığı için eğer ilk elemanın adresini bilirsek diğer elemanlara da kolayca erişebiliriz.

C'de dizi tanımlama örnekleri:

char  mesaj[]="Bu bir karakter dizisidir.";
float haftalik_yagis[7];
unsigned char   renk_rgb[]={88,153,240};

Yukarıda dizi tanımlamak için kullanılan üç farklı yöntem yer alıyor. Bu kullanımlar bu şekliyle C programlama dilinde sıkça kullanılır. İlk satır mesaj değişkenine tanımlı bir char dizisidir. C programlama dilinde çift tırnak içine yazılan ifadeler string olarak değerlendirilir. Köşeli parantezler boş bırakılarak dizi için string uzunlugunun bir fazlası bellek alınıyor ve belleğe mesaj kaydediliyor bu işlemi bizim yerimize derleyici yapıyor. Bu tip tanımlanan dizilerde eleman sayısı belirtilmzse dizi içeriğinin yazılması zorunludur. Kısaca uzunluğu belli olmayan bir dizi tanımlayamayız.

İkinci satır ise haftalık yağış miktarını tutmak için oluşturulmuş 7 elemanlı (her eleman float'tır) dizidir. Dizinin elemanlarına bir atama yapılmamış.

Üçüncü satır ise renk kaydetmek için kullanılan bir dizidir parantez boş bırakılmış ve deger girilmiş dizinin eleman sayısı 3 tür. Bu tip sayısal değerler verilirken süslü parantezler kullanılır ve değerler örnekte görüldüğü gibi virgülle ayrılır.

haftalik_yagis[0]=4.85;
haftalik_yagis[1]=2.13;
haftalik_yagis[6]=9.87;

C programlama dilinde dizi elemanları sıfırdan başlar haftalik_yagis dizisinin 1. elemanı haftalik_yagis[0] dır. Tanımlarken kullanılan rakam dizi uzunluğunu gösterir ama veri kaydederken yada veri okurken kullandığımız rakam ise dizi elemanını gösterir, buna dikkat etmek gerekir. Örneğin haftalik_yagis[7] hatalı bir kullanımdır dizi sıfırdan başladığı için 7. elemanı 7 değil 6 dır. Yukarıda haftalik_yagis dizisinin farklı elemanlarına değerler atanıyor.

İşaretçiler (Pointer)

İşaretçiler C pprogramlama dilinin en zor konusu olarak bilinirler. Gerçekte bu kadar zor değildir ama kullanımları tecrübe ile gelişir zor olan kısmı burasıdır. Öğrenirken pek zorluk çekmezsiniz.

İşaretçiler adres kaydedilen değişkenlerdir diğer değişkenlerin adresini tutarlar. Özellikle dizilerde sıkça kullanılırlar. Dizinin tanımlandığı değişken ismi yalın hali ile bir işaretcidir. Diziler sıralı verilerden oluşur örneğin bir text dosyasını programınızda açtığınızda text dosyasının verileri bir diziye kaydedilir. Dosya üzerinde yapacağınız değişikliklerde pointer kullanmanız gerekir. Örneğin dosyanın ilk 15 karakterini silmek istiyorsunuz. Bunu yapmak için dizinin başlangıç adresini tutan işaretçiyi 15 arttırmak yeterlidir.

İşaretçilerle kullanılan oparatörler

* İşaretçi tanımlamak için kullanılır. Örnek: int * pt; Tanımlanmış bir işaretçinin başında kullanılırsa işaretçinin gösterdiği adresin içeriği anlamına gelir, ve bu içeriğe normal bir değişken gibi atama yapıp okuyabiliriz. Örnek:  * pt=85;  Artık pt'nin gösterdiği adresin içeriği 85 oldu.
& Başına yazıldığı değişkenin adresini verir.Örnek: &deger değer değişkeninin adresidir ve bir işaretçiye kaydedilebilir.

Aşağıda iki farklı tür değişken için işaretçi tanımı yapılıyor.

int * pt;  //int tipinde işaretçi tanımı
char * st; //char tipinde işaretçi tanımı

 

#include <stdio.h>   //Standart giriş çıkış dosyası

int main(){

int * isaretci;   //Pointer tanımı
int deger=85;     //Değişken tanımı


isaretci=&deger;          //deger degişkenin adresi isatretçiye kaydediliyor
*isaretci=56;             //İşaretçinin gösterdiği adrese 56 sayısı kaydediliyor
printf("deger=%d",deger); //Değişken içeriği ekrana yazdırılıyor


getchar();       //Enter tuşuna basılana kadar bekle

return 0;        //Programdan çık

}

 

Yukarıdaki örnekte işaretçi tanımı yapılıyor bu tanım tüm değişken tipleri için geçerlidir, "char * pt;" doğru bir tanımlama biçimidir. İşaretçiye bir değer aktarırken bunun gerçek fiziksel bir adres olduğuna dikkat edin. Bu denetimi derleyici yapamaz. Pointerın içine kaydedilen her sayının bir adres olduğunu varasayarak o adresteki veriye ulaşmaya çalışır ve bu geçerli bir adres değil ise ya da işletim sisteminin kullandığı bellek adresi aralığına denk geliyorsa program hatalı çalışır ve sistem bozulabilir. Bu yüzden işaretçilere direk rakamsal değer girilerek atama yapılmaz değişkenlerin adresleri atanır. Örneğe geri dönecek olursak deger değişkeninin adresi işaretciye kaydediliyor. Üçüncü adımda ise işaretçinin gösterdiği adrese rakamsal bir değer kaydediliyor. Burada işaretçinin başındaki yıldız işareti verinin işaretçinin gösterdiği adrese yazılacağını ifade eder. Dolaylı olarak deger degişkeninin içeriği değişmiş oluyor.

Burada adres ve veri ayrımını iyi yapmak gerekiyor. Adres fiziksel bir konumu gösterir ve değiştirilemez. Veri ise bir adresin içeriğidir ve program yardımı ile değiştirilebilir. isaretci=&deger bu doğru bir kullanımdır tersi ise &deger=23; bu ifade ile adresi değiştirmeye çalışılıyor ve yanlış bir kullanım. Bunun için bütün derleyiciler hata verir.

İşaretçilerin (pointer) dizilerle kullanımı

İşaretçilerin genel kullanım alanı diziler ve struct yapılarıdır.

char  mesaj[]="Bu bir karakter dizisidir.";

char * pt;
pt=mesaj;     //mesaj değişkeni yalın haliyle bir işaretçidir
pt=&mesaj[0]; //mesaj dizisinin 1.elemanının adresi aynı zamanda dizinin başlangıç adresidir.

 

Yukarıda mesaj dizisi iki farklı şekilde işaretçiye aktarılıyor iki kullanımda doğrudur.  mesaj değişkeninin kendiside bir işaretçidir ve bu kullanım tüm diziler için geçerlidir.

İşaretçilerin en sık kullanıldıkları alan dizilerdir. Bunun nedeni dizileri bellekte bir yerden başka bir yere taşımanın zaman almasıdır, bunun yerine dizinin başlangıç adresi  kullanılarak değişik fonksiyonların dizi üzerinde çalışmasına olanak sağlamasıdır.

Dinamik dizi tanımlama ve kullanma

C'de derlenme sırasında uzunluğunu bilmediğimiz dizileri tanımlamamız gerekebilir. Örneğin kullanıcının seçtiği bir dosyayı diskten okuduğumuz zaman verileri kaydedeceğimiz dizinin uzunluğunu önceden bilemeyiz. C'de bu ve benzer durumlarda dinamik bellek kullanılır. Program çalışırken 'malloc' fonksiyonu ile işletim sisteminden istenen uzunlukta bir bellek bloğunun başlangıç adresini alabiliriz ve bu adresi bir diziyi gösteren pointer (işaretçiye) kaydederek istediğimiz uzunlukta bir dizi oluşturmuş oluruz.

C'de dinamik dizi tanımlama örneği:


#include <stdio.h>
#include <stdlib.h> int main(){ char * veri; int i; int veri_uzunlugu=10; //Veri uzunluğunun 1 fazlası uzunlukta bellek alınıyor. veri=(char *)malloc(veri_uzunlugu+1); if(veri==NULL){ //İstenen uzunlukta bellek alınamazsa hata mezajı yazılıyor ve programdan çıkılıyor. printf("Bellek hatası.\n"); return 1; } //veri dizisinin içeriğine X harfi yazılıyor for(i=0;i<veri_uzunlugu;i++){ veri[i]='X'; } //Dizinin son elemanına 0 değer verilerek string sonlandırılıyor. veri[i]=0; //Dizi içeriği ekrana yazdırılıyor. printf("%s",veri); //Alınan bellek geri veriliyor. free(veri); return 0; }