Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Çiğdem Çavdaroğlu
Çiğdem Çavdaroğlu
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
28 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: degeri degerleri degisken degiskeni fonksiyon fonksiyona fonksiyondan fonksiyonu fonksiyonun ifadesi islemyap(int nesnenin parametre return sonraki C / Sys Prog. Çiğdem Çavdaroğlu
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Başlangıç
Kategori : C / Sys Prog.
Yayınlanma Tarihi : 29.7.2005
Okunma Sayısı : 46793
Yorum Sayısı : 1     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 26.12.2024
Turhal Temizer
Mac OS/X Removing CUDA 26.12.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 26.12.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 26.12.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
Değer İle Çağırma - Referans İle Çağırma Kavramları
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu yazımızda, "değer ile çağırma" ve "referans ile çağırma" kavramlarının anlamlarına ve uygulamada ne şekilde karşımıza çıkacaklarına değineceğiz. Değer ile çağırma ve referans ile çağırma terimlerinin İngilizce karşılıkları sırasıyla "Call by Value" ve "Call by Reference"dır. Peki bu terimler ne anlama gelmektedir? Örneğin bu terimler ile parametre değişkenlerinin fonksiyonlara aktarımı sırasında karşılaşırız. int türden bir parametre alan bir fonksiyona, çağrımdan önce tanımladığımız int türden bir değişkeni parametre değişkeni olarak geçtiğimiz zaman, fonksiyonun parametre değişkeni için geçici bir nesne yaratılır ve bizim fonksiyona göndermiş olduğumuz değişkenin değeri bu geçici nesneye aktarılır. Dolayısıyla fonksiyonun parametresinin değeri ile bizim fonksiyona geçtiğimiz değişkenin değeri aynı olur. Ancak bu iki nesne aynı nesne değildir. Bellekte bu noktada iki tane birbirinden farklı ancak aynı değere sahip nesne bulunmaktadır. Bu durum "değer ile çağırma" olarak bilinir. Bir örnekle bu durumu açıklayalım :

int IslemYap(int parametre)
{
    return parametre * parametre;
}
//...
int sonuc, degisken = 5;
sonuc = IslemYap(degisken);
Örnekte tanımladığımız fonksiyon int türden bir parametre alıyor. Fonksiyon, bu parametrenin karesini alarak bu değere geri dönüyor. Örneğin devamında, "sonuc" ve "degisken" isimlerinde int türden iki nesne tanımlıyoruz. Daha sonra "degisken" nesnesini, IslemYap() fonksiyonuna parametre olarak geçerek geri dönen değeri "sonuc" nesnemize atıyoruz. Fonksiyonu çağırdığımız noktada, fonksiyonun parametresi için int türden geçici bir nesne yaratılır. Bu nesneye "degisken" nesnesinin değeri, yani 5 değeri atanır. Fonksiyon içerisindeki işlemler bu geçici nesne üzerinde yapılır. Fonksiyon return ifadesi ile son bulduktan sonra bu geçici nesne de yok edilir. Peki fonksiyonu şu şekilde yazmış olsaydık ne ile karşılaşacaktık?

void IslemYap(int parametre)
{
    parametre *= 2;
} int main()
{
    int degisken = 5;
    printf("ilk deger :%d\n",degisken);
    IslemYap(&degisken);
    printf("cagridan sonraki deger :%d\n",degisken);
    return 0;
}

Burada IslemYap() fonksiyonunda, fonksiyonun parametre degiskeninin değeri değiştirilmiştir. Fonksiyon herhangi bir değer geri döndürmemektedir. Böyle bir fonksiyonun yazılmasındaki amaç, büyük ihtimalle parametre değişkeninin değeri değiştirmektir. Kod içerisinde, fonksiyonu değeri 5 olan bir değişken ile çağırıyoruz. Değişkenin değerinin, fonksiyonun yaptığı işe göre 10 olmasını bekliyoruz. Ancak ikinci printf() çağrısı ile de ekrana 5 yazılıyor. Bunun nedenini şöyle açıklayabiliriz : Fonksiyonun parmetre değişkeni olan nesne, fonksiyon çağrıldığında derleyici tarafından tanımlandığı türde yaratılır. Bu nesneye, fonksiyon çağrılmasında kullanılan nesnenin değeri aktarılır. Bu noktada bizim fonksiyonumuzun parametre değişkeninin değeri 5’tir. Fonksiyon bloğu içerisinde bu geçici nesnenin değeri "parametre *= 2;" ifadesi ile 10 yapılır. Fonksiyonun bloğu sonlandığında bu geçici nesne de yok edilir. Yani değeri 10 olan nesnemiz artık yoktur. Bizim fonksiyonumuzu çağırırken kullandığımız nesnenin değeri ise hala 5’tir. Çünkü biz bu fonksiyonu, "call by value" yöntemine göre yani "değer ile çağırma" yöntemine göre tanımlamışız. Bu durumu şekille ifade edelim :

   

Yukarıdaki şekillerde yazdığımız kodda tanımlanan nesnelerin bellekteki temsili görünümlerini görüyoruz. degisken isimli nesnenin bellekte 1000 adresinde ayrıldığını varsayalım. (Buradaki adres değerleri tamamen örnek olarak verilmiştir.) Fonksiyonun ana bloğuna girildiğinde parametre değişkeni için 3000 adresinin ayrıldığını düşünelim. Bu durumda fonksiyon içerisinde paremetre değişkeni üzerinde yapılan değişikliklerden belleğin 3000 adres bölümü etkilenecektir. degisken isimli nesnenin bulunduğu 1000 adres değerine sahip bölge bu değişiklikten etkilenmeyecektir. Fonksiyon sonlandığında parametre değişkeni için ayrılan bölge de boşaltılacağı için değişiklikler sonucunda elde ettiğimiz değeri de kaybetmiş olacağız.

Bir nesnenin değerini, bir fonksiyon içerisinde değiştirmek istiyorsak; bu fonksiyona nesnenin değerini değil, referansını göndermeliyiz. Başka bir deyişle, fonksiyonumuz bu nesnenin bellekteki konumuna giderek yapacağı değişiklikleri orada yapmalıdır. Aksi takdirde hiçbir nesnenin değerini fonksiyon içerisinde değiştiremeyiz. Sadece bu nesnenin değerini kullanarak, geçici nesneler üzerinde işlem yapabiliriz. Yukarıda yapmak istediğimiz işlemi şöyle bir kod yazarak gerçekleştirebiliriz :

void IslemYap(int *parametre)
{
   *parametre *= 2;
} int main()
{
    int degisken = 5;
    printf("ilk deger :%d\n",degisken);
    IslemYap(&degisken);
    printf("cagridan sonraki deger :%d\n",degisken);
    return 0;
}

IslemYap() fonksiyonunun bu hali, parametre değişkeni olarak int türden bir adres almaktadır. Bu adresteki değere (*parametre) ifadesi ile erişiyoruz ve 2 ile çarpıp fonksiyonu sonlandırıyoruz. Şimdi fonksiyonu çağırırken parametre değişkeni olarak degisken nesnesini değil, bu nesnenin adresini gönderiyoruz. Dolayısıyla fonksiyon içerisindeki değişiklikler bu adres üzerinde gerçekleiyor. Fonksiyondan çıkıldığında ise bu adres bölgesi henüz boşaltılmadığı için degisken isimli nesneye ulaştığımızda 10 değerini elde ediyoruz. Bu şekilde çağırma "Call by Reference", yani "referans ile çağırma" olarak bilinir. Bu çağırmada fonksiyona parametre değişkeni olarak nesnenin değeri değil, kendisi gönderilmiş olur. Bu değeri elbette fonksiyondan return ifadesi ile geri döndürerek de elde edip çağırdığımız yerde bir değişkene atayabilirdik. Ancak bir fonksiyondan birden fazla sayıda değer elde etmek istiyorsak bu işlem için referans ile çağırma yöntemini tercih etmemiz gerekir. return ifadesi ile fonksiyondan ancak bir değeri geri döndürebiliriz. Örneğin bir fonksiyondan bize bir sayının hem karesini hem de küpünü göndermesini istiyorsak return ifadesine hangi değeri yazacağız? Bu işlem için fonksiyona parametre değişkeni olarak iki adres gönderirsek, elde ettiğimiz değerleri bu adres bölgelerine yazıp fonksiyon çağrısından sonra bu bölgelere erişebiliriz :

void KareVeKupAl(int sayi,int *kare, int *kup)
{
    *kare = sayi * sayi;
    *kup = sayi * sayi * sayi;
}

int main()
{
    int *karesi, *kubu;
    int sayi = 5;

    karesi = (int *)malloc(sizeof(int));
    kubu = (int *)malloc(sizeof(int));

    printf("Sayi :%d\n",sayi);
    KareVeKupAl(sayi,karesi,kubu);
    printf("Karesi :%d\n",*karesi);
    printf("Kubu :%d\n",*kubu);

    return 0;
}

KareVeKupAl fonksiyonu parametre değişkeni olarak, karesi ve küpü alınacak sayısı, daha sonra elde ettiği değerleri yazacağı adresleri alıyor. Fonksiyonu çağırırken karesini almak istediğimiz sayıyı ve elde edilen değerleri saklamak istediğimiz ve çağrıdan önce tahsis ettiğimiz güvenli adres bölgelerini gönderiyoruz. Fonksiyon çağrısından sonra bu adres bölgelerine erişerek fonksiyondan elde edilen değerleri yazdırıyoruz. Bu şekilde birden fazla sayıda değer döndürmesi gereken fonksiyonların bu şekilde yazılması gerekir. (Ya da bir yapı tanımlayarak geri dönüş değerlerini yapının elemanlarında tutabilirsiniz.)

Diziler üzerinde birtakım işlemler yapan fonksiyonlar yazmak istediğimizi düşünelim. Örneğin ilk olarak int türden bir dizinin tüm elemanlarının değerlerini birer artıran bir fonksiyon yazalım. Bunu değer ile çağırma yöntemine göre yazamayız. Diziler her zaman fonksiyonlara referansları ile aktarılır. Bunun yerine dizinin başlangıç adresini ve uzunluğunu parametre değişkeni olarak alıp, fonksiyon içerisinde dizi elemanları üzerinde dolaşarak doğrudan elemanlara erişir ve değerleri güncelleriz. Bu fonksiyonu yazalım :

void IslemYap(int *dizi,int uzunluk)
{
    int i;
    for (i = 0; i < uzunluk; ++i)
       dizi[i]++;
} int main()
{
    int i;
    int dizi[] = {1,2,3,4,5};

    printf("dizinin ilk hali :\n");
    for (i = 0; i < 5; ++i)
       printf("%d~",dizi[i]);

    IslemYap(dizi,5);

    printf("\ndizinin fonksiyon cagrildiktan sonraki hali :\n");
    for (i = 0; i < 5; ++i)
       printf("%d~",dizi[i]);

    return 0;
}

Bu fonksiyonda, parametre değişkeni olarak int türden bir adres ve bir de uzunluk bilgisi alıyoruz. Fonksiyon bloğu içerisinde bu adresten itibaren uzunluk değeri kadar adım adım ilerliyor ve ilgili adreslerdeki değerleri birer artırıyoruz. Örneğin dizi isminde 5 elemanlı bir dizi tanımladık ve fonksiyona bu dizinin başlangıç adresini gönderdik. Hatırlayacağınız üzere C dilinde dizi isimleri, dizilerin başlangıç adreslerini belirtir. Fonksiyondan çıkıldıktan sonra artık dizimizin elemanlarının değerleri birer artırılmış durumdadır.

Bu yazımızda değer ile çağırma ve referans ile çağırma kavramlarına ve ne zaman hangi yöntemi kullanmamız gerektiği konusuna değindik. Sonraki yazılarımızda görüşmek dileğiyle mutlu günler dilerim.

Makale:
Değer İle Çağırma - Referans İle Çağırma Kavramları C ve Sistem Programlama Çiğdem Çavdaroğlu
  • Yazılan Yorumlar
  • Yorum Yaz
TEM
23
2006
Benim bildigim refrans void KareVeKupAl(int sayi,int kare&, int kup&) seklinde veriliyordu.Gerci yapilan is ve gerceklesen olay ayni ancak syntax olarak boyle olmasi laizm referansin.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • 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