Forum: Diğer Konular RSS
C++ İşaretçiler ile reverse Fonksiyonu
İbrahim #1
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: C++ İşaretçiler ile reverse Fonksiyonu
Selam;
Ben C++'da işaretçiler kullanarak şöyle bir reverse fonksiyonu yazdım:
void reverse(int* n1, int* n2)
{
  if (*n1 > *n2)
  {
    int tmp = *n1;
    *n1 = *n2;
    *n2 = tmp;
  }
}
 
int main()
{
  int n1 = 5;
  int n2 = 3;
 
  reverse(&n1, &n2);
 
  cout << "n1 = " << n1 << endl
         << "n2 = " << n2 << endl;
  return 0;
}

Bu kod çıktıda şu sonucu veriyor: n1 = 3, n2 = 5.
reverse fonksiyonunu şöyle değiştirdiğimde sonuç n1 = 5, n2 = 3 oluyor yani değişkenlerin değerleri değişmiyor.
void reverse(int* n1, int* n2)
{
  if (*n1 > *n2)
  {
    int* tmp = n1;
    n1 = n2;
    n2 = tmp;
  }
}
 
int main()
{
  int n1 = 5;
  int n2 = 3;
 
  reverse(&n1, &n2);
 
  cout << "n1 = " << n1 << endl
         << "n2 = " << n2 << endl;
  return 0;
}
Fakat bu mantık bana doğru geliyor çünkü işaretçilerin değerleriyle oynamak yerine adresleriyle oynayıp birbirlerinin değerlerini almalarını bekliyordum. Buradaki mantık nedir? Adreslerini değiştirdikten sonra adreslerini ekrana yazdırıyorum ve adreslerin birbirleriyle değiştirildiğini görüyorum ama değerler değişmiyor, sonuçta değerler de o adreslerde tutuluyor.

Teşekkürler!
Avatar
zekeriyadurmus #2
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
int* diye tanımladığın şey aslında 4 baytlık sayı ve bir adresi temsil ediyor.

İlk kod örneğinde fonksiyona adresleri argüman olarak veriyorsun ve o adreslere erişip değerlerini değiştiriyorsun.

Öte yandan ikinci kod örneğinde ise elinde adresin bulunduğu değişkene farklı bir adres atıyorsun. Bu n1 veya n2 üzerinde en ufak değişikliğe sebep olmayacaktır.

n1 ve n2 stack üzerinde saklanıyor ve stack üzerindeki değişkenlere [EBP - 4] [EBP - 8] şeklinde erişiliyor (asm boyutunda). Sen &değişken yaptığında ise lea EAX, [EBP + 4] tarzı bir komutla direk yazaçın (register) üzerine adresi atıyor ve reverse fonksiyonu içerisindeki n1 ve n2 değişkenlerine o adres veriliyor. Senin orada n1 üzerinde işlem yapmanın bir anlamı yok kısaca ve adreslerini değiştirmen mümkün değil. Program derlenirken her yerel(local) değişken için [EBP - 4] gibi bir asm kodu yazıldı.

Yazılan kodun makine kodu çıktısını da incelersen eğer olayı çok daha iyi kavrayabilirsin.

Eminim Ali hocam çok daha basit bir dille anlatabilir.

Dipnotlar:
EBP => Base Pointer ( bunlarla alakalı güzel bir stackoverflow linki buldum http://stackoverflow.com/questions/1395591/what-is-exactly… )
[EBP - 4] aslında dword ptr [EBP - 4] ve anlamı EBP-4 adresindeki değeri oku.
lea => load effective address (bir yazacın üzerine adresteki veriyi okumak yerine adresi yazıyor. Hesaplama yaparken de kullanıldığını gördüm.)

Zekeriya
Bilgi meraktan gelir...
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ı
Derleyicinin ne yaptığı tabii ki önemli ama bu gibi kavramları oralara inmeden açıklayabilmeliyiz. Buradaki önemli konu, parametre değerlerinin işlevlere hep kopyalanarak geçiriliyor oldukları. İşlev içindeki n1'in main içindeki gösterge ile bir ilgisi yok:

  http://ddili.org/ders/d/islev_parametreleri.html#ix_islev_…

Ek olarak, eğer dil kuralı başka olsaydı ve işlevdeki değişiklik main içindeki göstergeyi etkileseydi, bu durumda yine işe yaramazdı çünkü main içinde gösterge değişkeni yok. main içinde &n1 diye geçirilen değer bir sağ değerdir. Sağ değerler değiştirilemez:

  http://ddili.org/ders/d/deger_sol_sag.html#ix_deger_sol_sa…

İlgisiz iki nokta:

  • Bu işlevin adı reverse olmamalı çünkü işini koşullu olarak gerçekleştiriyor. Belki sıralama anlamı veren bir ad seçilebilir.

  • main içindeki değişkenlerle işlev parametrelerine aynı isimleri vermek kafa karıştırıyor olabilir.

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, 09:30:33 (UTC -08:00)