Forum: D Programlama Dili RSS
isaretciler uzerine..
Mengu (Moderatör) #1
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: isaretciler uzerine..
merhabalar,

c ve c++'ta gordugumuz isaretciler, d dilinde de mevcut. madem hem c++'in hem de d'nin ustadlari burada, isaretcilerin kullanilmadigi java, c# ve python gibi dillerle mesgul kisilere isaretcilerin ne oldugunu, ne ise yaradigini, nerede, ne zaman ve nasil kullanilmasi gerektigini anlatirsaniz cok iyi olur diye dusunuyorum.

simdiden tesekkurler.
http://www.mengu.net - some kind of monster
emre413 (Moderatör) #2
Kullanıcı başlığı: Celal Emre ÇİÇEK
Üye Tem 2009 tarihinden beri · 62 mesaj · Konum: Kırıkkale
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet hocam ben de pointer konusunu şöyle böyle biliyorum ama tam olarak neden kullanılır onu bilmiyorum. Yani bir değişkenin adresini bilmek bize ne kazandırır? Pointer'a değer atamak daha mı hızlıymış ne?

Mengu:
Bildiğim kadarıyla C#'ta unsafe içinde pointer kullanılıyor.
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Bundan uzun bir makale çıkar. :) Ben çok kısa maddeler halinde ve hızlıca düşüneceğim.

İşaretçi, "bu işlem sırasında beni değil, benim gösterdiğim şeyi kullan" diyen şeydir.

= C =

- C'de parametreler fonksiyonlara kopyalanarak geçirilirler (by-value) ve bu fonksiyonel programlama açısından iyi bir şeydir

// Fonksiyonel programlama; yan etki yok; değer üretip döndürüyoruz:
int ikiye_bol(int sayi)
{
    return sayi / 2;
}
 
// ...
 
benim_sayi = 10;
benim_sayi = ikiye_bol(benim_sayi);   // == 5 

- Parametreleri referans olarak geçirmek için C'de işaretçiler kullanılır. O zaman fonksiyona "bu parametrenin kopyasını değil, parametrenin gösterdiğini kullan" demiş oluruz:

// Bunun yan etkisi var; sonuç üretmiyoruz, parametreyle gösterileni değiştiriyoruz:
void ikiye_bol(int * sayi)
{
    *sayi /= 2;
}
 
// ...
 
benim_sayi = 10;
ikiye_bol(&benim_sayi);    // == 5 

emre413, performans, böyle anlamsal kavramların yanında önemsiz bir nedendir. İşaretçiler daha hızlı oldukları için kullanılmazlar. Hatta duruma göre daha yavaş olabilirler:

- Kopyalanan bir yapının üyeleri hemen hazırlardır ve erişimleri çok hızlıdır; oysa işaretçi üzerinde erişmek zaman alır

- İşaretçilerin mikro işlemcinin ara belleğine sığma şansları daha azdır, çünkü işaretçi ve işaret ettiği şey bellekte uzakta bulunuyor olabilirler

Ölçmek lazım... :)

= C++ =

- C++'ın amaçlarından birisi C'ye olabildiğince bağlı kalmak olduğu için kopyalanan ve işaretçi olarak geçirilen parametreleri aynen destekler

- Ek olarak, aslında işleç yükleme olanağının bir hediyesi olan referans kavramını da getirir:

// Yine yan etkisi var:
void ikiye_bol(int & sayi)
{
    sayi /= 2;
}
 
// ...
 
benim_sayi = 10;
ikiye_bol(benim_sayi);    // == 5 

Referanslar "takma isim" gibidirler. Yukarıdaki durumda, fonksiyonun parametresi olan sayi, ona geçirilen benim_sayi'nin takma ismidir. O yüzden sayi/=2 yapınca benim_sayi değişir

= D =

Not: Bunları ben de yeni öğreniyorum. Böyle sorulara devam! :D

D'de struct ve class C++'ın aksine oldukça ilgisiz kavramlardır.

- struct'lar değer nesnelerini gösterirler:

struct Renk { int kirmizi; int yeşil; int mavi; }
 
struct Öğrenci { /* ... */ }

Yani bir grup verinin bir araya getirilmesinden oluşmuş yapılar.

struct'lar özel bir şey yapılmazsa kopyalanarak geçirilirler.

- class'lar ise çokşekillilikte görülen referans kavramlarını gösterirler: Örneğin bir Hayvan sıradüzeni ve ondan türeyen Kedi, Köpek, vs. class'ta önemli olan, nesnenin davranış farkıdır.

D'de class'lar referans olarak geçirilirler.

- D'de parametrelerin nasıl kullanıldıklarını C++'ta olmayan şekilde belirleyebiliriz ve böylece struct'ları da referans olarak geçirmek mümkündür:

in: yalnızca giriş bilgisi olarak kullanılır ve değiştirilemez

out: yalnızca çıkış olarak kullanılır; fonksiyon içinde ilklenir ve çağıran tarafa kopyalanır

ref: referans olarak geçirilen parametreleri bildirir (D'de C++'ın referans anlamına gelen & işleci yoktur)

- Ek olarak, D'nin alias anahtar sözcüğü de başka bir nesnenin "takma ismi" olarak yine onun yerine geçer; yani onun "referansıdır"

import std.stdio;
 
// struct olduğu için normalde kopyalanarak geçirilir
struct S
{
    int i;
}
 
void foo(in  int değişmez,
         out int ilklenir_ve_kopyalanır,
         ref S   referans_olarak_geçirilir)
{
    // HATA: Değiştirilemez!
    // değişmez = 1;
    ilklenir_ve_kopyalanır = 111;
    referans_olarak_geçirilir.i = 222;
}
 
void main()
{
    int i = 10;
    int j = 20;
    S s;
 
    foo(i, j, s);
 
    alias i takma_isim;
    
    writeln(i, " ", j, " ", s.i);
 
    // Bu sayede i değişir
    takma_isim = 333;
    writeln(i);
}

- Daha ek olarak, D'de işaretçiler de vardır; ama yukarıdaki çeşitli olanaklar nedeniyle kullanımlarına belki de hiç gerek kalmaz.

Bildiğim ve uydurduğum kadarı böyle... ;)

Ali
Mengu (Moderatör) #4
Kullanıcı başlığı: NONSERVIAM
Üye Tem 2009 tarihinden beri · 347 mesaj · Konum: Dersaadet
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
isaretciler bugun kullandigimiz in, out ve ref nesneleri yerine kullaniliyordu fakat artik bunlar oldugu icin isaretcilere ihtiyacimiz olmadigini soyleyebilir miyiz?
http://www.mengu.net - some kind of monster
acehreli (Moderatör) #5
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Fazlasıyla fonksiyonlara eğilmişim... :/

İşaretçilere gerek olmadığını söyleyemeyiz. Örneğin bir bağlı listede yine de sonraki düğümü göstermek gerekir.

Ayrıca fonksiyonlardan NULL döndürmek hâlâ geçerli bir tasarımdır. Örneğin aranan bir şey bulunmadığındı "yok" anlamında NULL döndürülebilir.

Daha da önemlisi, D C standart kütüphanesini olduğu gibi destekler. En azından o yüzden işaretçilere bulaşmak gerekir.

Ali
Avatar
esatarslan52 (Moderatör) #6
Üye Haz 2009 tarihinden beri · 142 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Hem out hemde ref ikisi de fonksiyona gönderildikten sonra başka bir yerde kullanıldığında fonksiyon içinde geçirdikleri değişiklik geçerli oluyo. "ref" de bir sorun yok fakat  "out" un açıklamasını anlayamadım :blush: .

"in" , "const" ve "immutable" bu 3 ü yaklaşık olarak aynı işi yapmıyolarmı?

Birde "delegate" var. Başka bir örnekte fonksiyona parametre olarak başka bir fonksiyonun adresini göndermek için kullanıldığını görmüştüm(en azından ben öyle anlamıştım).Normal değişkenler içinde delegate kullanılabilir mi?

Çok fazla kavram var  <_<
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Fonksiyon parametreleri bilgilerinin kaynağı şurası:

  http://digitalmars.com/d/2.0/function.html

Yaklaşmışsın: in galiba const scope'un eşdeğeri

ref, parametrenin değerini fonksiyon içinde de kullanıyor. Yani giriş/çıkış için. out ise parametreyi fonksiyon içinde ilkliyor. Yani yalnızca çıkış...

delegate, galiba iki şeyin bir araya getirilmesi: bir nesne ve onunla yapılacak iş... delegate'i fonksiyon parametresi dışında görmedim ama eğer gerçekten ikisini bir araya getiriyorsa, bir delegate dizisi de düşünülebilir. Elektrikler kesikti, çalışamadım... :-p

Kavramlar gerçekten çok. :(

Ali
li-han #8
Üye Ağu 2009 tarihinden beri · 8 mesaj · Konum: Denizli
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
out, ref konusunda şöyle bi test yaptım:

import std.stdio;
 
void main()
{
    int outDeğer=2;
    int refDeğer=7;
    
    writefln("1. durum = outdeğer: %d, refdeğer:  %d", outDeğer, refDeğer);
    
    SonuçYaz(outDeğer, refDeğer);
    
    writefln("3. durum = outdeğer: %d, refdeğer:  %d", outDeğer, refDeğer);
}
 
void SonuçYaz(out int outDeğer, ref int refDeğer)
{
    writefln("2. durum = outdeğer: %d, refdeğer:  %d", outDeğer, refDeğer);
    outDeğer = 6;
    refDeğer = 10;
}
çıktı:

1. durum = outdeğer: 2, refdeğer:  7
2. durum = outdeğer: 0, refdeğer:  7
3. durum = outdeğer: 6, refdeğer:  10

Ali hocamın açıkladığı gibi ref parametrelerin değeri fonksiyon içinde kullanılabiliyorken out parametrelerin değeri fonksiyon içinde kullanılamıyor. out parametreler örnekte görüldüğü gibi 0 değeri veriyo. ama fonksiyon içinde verilen değer fonsiyon dışında kullanılabiliyor.
Avatar
esatarslan52 (Moderatör) #9
Üye Haz 2009 tarihinden beri · 142 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Kullanıla biliyor. Bende ilk başta senin gibi acaba out ile gönderilen parametre de sadece ilk değer ataması mı yapabiliyor diye düşünmüştüm. Ama kullanılabildiğini gördüm.
void foo(in  int değişmez,
         out int ilklenir_ve_kopyalanır,
         ref S   referans_olarak_geçirilir)
{
    // HATA: Değiştirilemez!
//     değişmez = 1;
    ilklenir_ve_kopyalanır = 111;
//Burda sorun çıkmıyo mesela
    referans_olarak_geçirilir.i = ilklenir_ve_kopyalanır*2;
}

Senin fonksiyonun sıfır göstermesinin nedeni "out" ile girilen parametrenin ilklenmesinden kaynaklanıyo. Değişkene fonksiyon içinde herhangi bir yerde değer ataması yapana kadar default değeri "0" olarak kabul ediliyo(D'nin ilk değer atama özelliği).

Kodu aşağıdaki şekle getirmen yeterli

void SonuçYaz(out int outDeğer, ref int refDeğer)
{
    outDeğer = 6;
    writefln("2. durum = outdeğer: %d, refdeğer:  %d", outDeğer, refDeğer);
    refDeğer = 10;
}
li-han #10
Üye Ağu 2009 tarihinden beri · 8 mesaj · Konum: Denizli
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
hım sanırım yanlış anlaşıldım kullanılamıyor derken. hiç bir şekilde kullanılamadığını kastetmemiştim. out parametre fonksiyon dışında aldığı değeri fonksiyon içinde kaybediyor desem daha doğru olurdu sanırım. dıştan içe bir değer aktarma özelliği yok adı üstünde out, içerden dışarı değer gönderebiliyor.
li-han #11
Üye Ağu 2009 tarihinden beri · 8 mesaj · Konum: Denizli
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
basit bi konuyu fazlaca uzatma niyetinde değilim ama senin mesajını tekrar okuyunca benim ilk mesajımı yanlış algıladığın kanısına vardım. ayrıca kavram kargaşasına mahal vermemek ve olayın net bi şekilde anlaşılabilmesini sağlamak amacıyla bu mesajı da yazayım dedim.

ilk mesajımda out parametrelerin değeri fonksiyon içinde kullanılamıyor. yazdım. evet taşıdığı değer fonksiyon içinde kullanılamıyor. çünkü sıfırlanıyor yani ilklendirme olayı.  outDeğer bir parametre değişkenidir ve pekçok programlama dilinde parametre değişkenleri, üyesi oldukları fonksiyon içinde yeni değer alabilir. senin verdiğin
void SonuçYaz(out int outDeğer, ref int refDeğer)
{
    outDeğer = 6;
    writefln("2. durum = outdeğer: %d, refdeğer:  %d", outDeğer, refDeğer);
    refDeğer = 10;
}
örneğinde olduğu gibi. benim mesajımdan bu değişkenin (outDeğer) kendisini kullanamayacağımız anlaşılmsın. dışardan getirdiği değeri kullanamayız diyorum.
çok mu uzattım bilmiyorum  :-D hatam varsa lütfen düzeltin.
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Alıştığımız kavramlardan farklı olunca ne kadar garip değil mi... :) Ben de baştan out'u hiç anlamamıştım çünkü kafamda diğer dillerden alıştığım gibi bir kopyalanma algılıyordum. :)

Halbuki örneğin C'deki işaretçi olarak geçirmek anlamına geliyor ve şu C programının eşdeğeri:

void foo(int * out_deger)
{
    // Once mutlaka ilkliyor:
    *out_deger = 0;
 
    // sonra deger verebiliyor:
    *out_deger = 42;
}
 
int main()
{
    // bu deger hic kullanilmiyor
    int i = 7;  
    foo(&i);
}

Böylece out anahtar sözcüğüyle o parametrenin kullanımı D'de daha iyi anlatılmış oluyor.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 07:33:35 (UTC -08:00)