12. Bölüm
Cenker Özkurt
Bu ayki konumuz, Dizi ve İşaret değişkenleri. Bildiğiniz gibi, geçen ay fonksiyonları ve C'nin program yapısını tam olarak öğrenmiştik. C öğrenecek arkadaşlara herşeyden önce şunu belirtmek isterim ki, yeni bir konuya geçmeden önce, bir önceki konuyu tam olarak öğrenin. Bu konularda kalan bir eksiklik yeni konulara da yansıyacak ve öğrenmenizi zorlaştıracaktır. Konuları anlamanın en iyi yolu da, bol bol örnekler yapıp bunların üzerinde çalışmak. Fakat başlangıçta örnek üretmek zor olabilir. Bundan sonra ben de bu konuda sizlere daha fazla yardımcı olmayı düşünüyorum. Diğer bir deyişle, bundan böyle sizlere kendi hazırladığım örneklerle yardımcı olmayı çalışacağım. Çünkü "The C Programming Languages" kitabından verdiğim örneklerin çoğu, yeni başlayanlara göre biraz ağır gelmekte. Bu sayımızdan başlayarak vereceğim yeni ve basit örnekler, sizin konuyu daha rahat anlamanızı sağlayacaktır.
Şimdi ilk olarak işaret değişkenlerini tanımlayarak bu ayki konumuza başlayalım.
İşaretler, değişkenlerin adresini göstermek için kullanılır. Yalnız işaret değişkenleri kullanırken dikkatli olmak gerekir. Farklı bir yazılımı olduğundan dolayı, programın anlaşılırlığını etkilemektedir, işaret değişkenlerinin diğer değişkenlerden adres gösterme dışında fazla bir farkı yoktur. Aynı şekilde global ya da local olabilirler. int, char veya diğer değişken tiplerinde tanımlanabilirler. Kullanım şekli bakımından oldukça yararlıdır.
İŞARETLER ve ADRESLER (Pointers and Adresses):
İşaret değişkenleri, devamlı olarak istenilen bir adresi gösterebilir ve bu adresin değerini değiştirebilir. Değişkenlerin adresini öğrenmenin diğer bir yolu da, '&' operatörünü kullanmaktır. Ama bu, gerçek anlamda 've' operatörü değildir. Yalnız adresini öğrenmek istediğimiz değişkenin başına konulur. Örnek olarak px ve x iki integer değişken olsun. px değişkenini, x değişkeninin saklandığı adresi göstermek için kullanalım. Yani,
px=&x;olarak yazılır. Buradaki işlem sonucunda px, x değişkeninin kullandığı adresi gösterecektir. Eğer biz x değişkeninin kullandığı adresle oynamak istersek, bunu px değişkenini işaret değişkeni olarak kullanarak yapabiliriz.
Bir değişkeni işaret değişkeni olarak tanımlamak için '*' operatörünü kullanırız. Aşağıdaki örnekte x ve y int, px pointer (işaret değişkeni) olsun:
y=*px;Burada, px bir pointer değişkendir. px'in başına '*' işareti koyarak px'in göstermiş olduğu adresin değerini alabiliriz.
px=&x; y=*px;Yukarıdaki örnekte ise px, x değişkeninin adresini almakta. Bu işlem sonucunda y değişkeni, x değişkeninin değerini alacaktır. Bu işlemlerden önce değişken tanımlamaları ise şöyle yapılmaktadır;
int x,y; int *px;Örnekten de anlaşılaşacağı gibi *px tanımlaması, diğerlerine göre biraz yeni. Tek fark ise, değişkenin başındaki '*' işareti. Böylece px artık bir pointer değişkenidir.
Şimdi pointer değişkenlerinin diğer kullanım şekillerine bakalım.
y=*px+1;
printf("y=%d",*px);
Bu örnek px'in gösterdiği adres değerinin bir fazlasını yazar.
y=*(px+1);
printf("y=%d",*px);
Bu örnekte ise, px'ten bir sonraki adresin değeri ekrana getirilmektedir.
*px=0;px'in gösterdiği adresin değeri sıfırlanır.
*px+=1;px'in gösterdiği adresin değeri bir artar.
İŞARET DEĞİŞKENLERİNİN FONKSİYONLARLA KULLANIMI:
Bir fonksiyonun içinde işaret değişkeni kullanılıyorsa, fonksiyon çağırılırken parametreler adres olarak verilir. Çünkü burada işaret değişkenleri tanımlandıktan sonra verilen parametreler, adres olarak alınmakta ve bu değişkenlere atanmaktadır.
swap(x,y)
int x,y;
{
int temp;
temp=x;
x=y;
y=temp;
}
Buradaki örnekte, x ve y'nin değerleri yer değiştirilmektedir. Fakat bu değişikliği yalnızca swap() fonksiyonu içinde kullanabiliriz.
swap(&px,&py)
int *px,*py;
{
int temp;
temp=*px;
*px=*py;
*px=temp;
}
Bu kullanım daha doğrudur. Çünkü artık değişkenler arasındaki değişikliği başka bir fonksiyonda da kullanabiliriz.
Buradaki örnek ise, hex olarak 30000'den 3000f'a kadar olan adreslerin içeriğini gösteren bir programdır.
main()
{
int *pa;
int f,a;
pa=0x30000;
for(f=0;f<=0xf;f++) {
a=*(pa+f);
printf("Adres=%x Değer=%d",pa+f,a);
}
}
Aşağıda vereceğim örnek ise, oldukça kullanılan bir örnektir. Mouse'unuzun sol tuşunu kontrol eder. 0xbfe001 adresi, bize mouse kontrol adresini vermektedir. Sol tuşa basıp adresi okuduğumuzda, 188 değerini alırız. Bu sayede mouse kontrolünü yapmış oluruz.
main()
{
int *pm;
pm=0xbfe001;
printf("Devam için Sol Mouse tuşuna basınız.");
while(*pm!=188);
}
Şimdiki örnekte ise, her tuşun gerçek port kodunu öğrenebilirsiniz.
main()
{
int *mouse=0xbfe001;
int *key=0xbfec01;
printf("Durmak için Sol Mouse tuşuna basınız,");
while(*mouse!=188) {
printf("kod=%d",*key);
}
}
Daha önce de söylediğim gibi, bu örnekleri çoğaltmak mümkün. Ben sizlere en çok kullandığım türden örnekler vermeye çalıştım. Siz bu örnekler üzerinde oynayarak konuya hakim olmaya çalışabilirsiniz.
İŞARETLER ve DİZİLER:
C'de pointer'lar ve diziler arasında oldukça sıkı bir bağ vardır. Dizilerdeki herhangi bir indise pointerler sayesinde rahatça ulaşabilirsiniz.
Aşağıdaki örnekte 'a', on elemanlı integer bir dizi olsun. Bu dizinin örneğin beşinci elemanına pointerler ile ulaşmaya çalışalım:
int a[10]; int *pa,x; pa=&a[0]; x=*(pa+5);Bu örnekte pa, a değişkeninin ilk adresini gösterecek şekilde tanımlanmaktadır. Doğal olarak beş byte sonrası da, a değişkeninin beşinci elemanının değerini verecektir.
pa=&a[0];yerine;
pa=a;da diyebiliriz. Ya da aşağıdaki örnekte olduğu gibi kullanabiliriz; f() bir fonksiyon olsun,
f(&a[2]);yerine
f(a+2);gibi. Şimdi ise, iki dizinin birbirine eşitlenmesi örneğini inceleyelim.
strcpy(s,t)
char s[],t[];
{
int i;
i=0;
while((s[i]=t[i]) !='0')
i++;
}
örneği pointerlar ile yapalım.
strcpy(s,t)
char *s, *t;
{
while((*s=*t) !='0'){
s++;
t++;
}
}
Bu örneği daha kısa biçimde yazmak gerekirse,
strcpy(s,t)
char *s, *t;
{
while((*s++=*t++)!='0');
}
'0' ifadesini, dizinin sonuna gelip gelmediğimizi kontrol etmek için kullanıyoruz. Fakat bunu en kısa biçimde şöyle de yazabiliriz.
strcpy(s,t)
char *s, *t;
{
while(*s++=*t++);
}
Burada, her iki dizinin değerinin sıfır olması şartıyla programdan çıkılabilir.
Dikkat ettiyseniz, pointerlar sayesinde istediğimiz bir değişkenin değerini rahatlıkla okuyup değiştirebiliyoruz. Bu da, programcılık açısından yukarıdaki örneklerden de anlaşılaşacağı gibi oldukça kolaylıklar sağlamakta. Fakat pointerlerin yararları bu kadarla bitmiyor. Bu yalnızca bir başlangıç. Bundan sonraki örneklerde de sıkça kullanacağımız pointer değişkenleri tam olarak anlamaya çalışın.
Bu aylık bu kadar. Gelecek aya oldukça önemli olan Structures (yapılar) konusunu inceleyeceğiz.
Hepinize iyi çalışmalar...