Pointerlar ve kullanımları

Yazan : Şadi Evren ŞEKER

Pointer (gösterici) basitçe bir değişkenin bir hafıza alanını göstermesi demektir. C dilinde pointerlar:

Veritipi *pointeradi;

Şeklinde tanımlanır. Burada veritipi int, char, float gibi değişken tipleridir. Pointer adı ise bir değişken adının taşıması gereken özellikleri taşıyan ve tanımlandığı scope (geçerlilik alanında) yaşayacak olan değişken adıdır.

Bir değişkenin başına & işareti geldiğinde ise bu değişkenin adresini temsil eder. Yani değişken hafızada nereye konulduysa bu konulan yerin adresine bu işaret ile ulaşılabilir.

Örneğin,

int *p;

int a=10;

p=&a;

satırından sonra hafızada integer değer gösteren p isminde bir pointer tanımlanmış olur. Bunu hafızda temsili olarak gösterecek olursak:

memory pointer locations

Yukarıdaki temsili resimde, ilk sütun adres değerlerini temsil etmektedir, buna göre hafızanın a101 ile a120 numaralı adresleri arasındaki bilgiler gösterilmiştir ( bu değerler hexadecimal olup temsili olarak yazılmıştır)

Kodda bulunan p ve a değerlerinin hafızda hangi bölüme atanacağı çalıştırma sırasında ( execution time ) belirlenir dolayısıyla tam olarak nerede bulunacağı bilinemez ancak p tanımlnadıktan sonra a107 adresine ve a tanımlandıktan sonra a116 adresinin ayrıldığını kabul edelim. Bu durumda p’nin değeri a107 numaralı adreste olacaktır.

Kodda a değerine 10 konulmuştur bu durumda a’nın değerinin durduğu a116 numaralı adreste sayısal olarak 10 yazacaktır.

Kodda a’nın taşıdığı adres değeri, p’nin içine atılmıştır. Bu durumda p’nin değeri a’nın adresi olacaktır.

Aşağıdaki örnek kodu çalıştırınız ve yorumlayınız:

#include

int main(){

int a=10;

int *p;

p=&a;

printf(“%dn”,*p); // p’nin gösterdiği yeri basar

printf(“%dn”,p); // p’nin değerini yani, p’nin gösterdiği yerin adresini basar

printf(“%dn”,a); // a’nın değerini basar

printf(“%dn”,&a); //a’nın adresini basar

printf(“%dn”,&p); //p’nin adresini basar

}

C dilinde her dizi bir pointer her pointer da doğal bir dizidir.

char str[80], *p1;
p1 = str;

Burada p1, str dizisinin – stringinin – ilk elamaninin adresinin degerini alir. Yani string adi, aslinda o stringin hafizadaki baslangiç adresini = stringin ilk karakterinin adresini tutmaktadir. str dizisinin 5. elemanina erismek için ise;

str[4] veya *(p1+4)

ifadelerini kullaniriz. Her ikisinin de anlami aynidir.

C’de dizi elemanlarina 2 sekilde ulasilir: pointer kullanimi ile ve indis kullanimi ile. Indis kullanimi gelistirme ve anlama bakimindan bir kolaylik saglasa da, hiz önemli bir konu oldugundan C programcilari genelde dizi erisimini pointer kullanarak yaparlar. Asagida ayni isi yapan iki fonksiyon yeralmaktadir:

void putstr(char *s)
{
int t;
for (t=0; s[t]; ++t) putchar(s[t]);
}
void putstr(char *s)
{
while (*s) putchar(*s++);
}

C dilinde bir pointer’ı array gibi kullanmak için:

int *p = (int *) malloc ( sizeof(int)*10);

şeklinde bir satır yazmak yeterlidir. Burada klasik dizi tanımından farksız bir işlem yapılmış, hafızada 10’luk bir alan açılmış ve tipi integer olarak tanımlanmıştır.

Pointer’ın farkı bu alana erişim şeklindedir. Yani dizi tanımlarında olduğu gibi köşeli parantezle (a[3] gibi) erişmek yerine pointer üzerinde işlem yapmak gereki ancak yöntem bir önceki örnekte olduğu gibi

printf(“%dn”,*(p+4)) şeklinde işleyebilmektedir.

Yorumlar

  1. Fatih Kabakci

    printf(”%dn”,&p); hocam bu sonuc hep 2293568 cıktısını veriyor.bu sabit bi degermi yoksa farklı varyasyonlarda sonuc farklı cıkar mi?

  2. Şadi Evren ŞEKER Article Author

    int *p;
    printf(“%d”,&p);
    kullanımı, p göstericisinin adresini basar. Bu gösterici her seferinde farklı bir adreste bulunabileceği için adres değeri değişebilir. Ancak aslında adres değerleri integer olarak gösterilirken problem olabilir. Bu yüzden bu kullanım sadece temsili bir kullanım olup fikir vermesi için yazıda bulunmaktadır.

    Sorunuzun cevabı, evet her çalıştırmada farklı bir adres alması mümkündür.

  3. gokhan.taskin

    Elimizde bir merhaba stringi olsun fonksiyon yerel bir değişkenle set edecek . Returnle değer döndürecek . Ana programda da ekranda merhabayı görmek istiyoruz .

    bu sekilde bir problem var cozmek istiyorum ama benden ne istediğini anlamadım hocam set etmek ne demek benden ne istiyon acıklarsanız sevinirim nasıl bir kod yazmalıyım

  4. hursit topal

    append

    insert(i,eleman)

    delete(i)
    index of(eleman)
    sort

    pythonda ki bu fonksiyonları C de nasıl gercekleriz

    hocam

  5. Ozan

    hocam tünaydınlar.hocam dun siz bana sezar şifrelem yontemini soylemıstınız.sımdı orneğin burdaki olayı anladım ama mesele orneğin bu bir dizi olsaydı mesela elemanları 10 22 2 44 simdi mesela burda bunu 2 defa cevir deseydik saat yonunde yine bu sezar sıfrleme yontemındeki mantıkla mı yapıcaz.yok bu ıkı soru tipi bırbırınden farklı mı?

  6. Şerif Muammer

    Çift boyutlu diziler pointer’lara nasıl aktarılır. Mesela matris toplamı yapan bir fonksiyona A[m][n] dizisini pointer yardımıyla gönderebilir miyim?

  7. Şadi Evren ŞEKER Article Author

    Her gösterici (pointer) bir dizi olarak kabul edilebilir. Örneğin

    int a[]
    veya
    int *a

    aynı anlama gelmektedir ve tek boyutlu dizidir.

    int a[][]
    veya
    int **a
    veya
    int *a[]

    aynı anlama gelmektedir ve iki boyutlu dizi demektir. Aslında iki boyutlu dizi, her elemanı dizi olan dizidir ve her elemanı gösterici olan dizi olarak ifade edileibilir. Veya her elemanı gösterici olan bir diziyi gösteren gösterici de olabilir. Bu yüzden int **a tanımı iki boyutlu dizi anlamındadır.

    Daha önce (Okan Üniversitesi, 2007-2008 bahar dönemi) verdiğim bir dersteki bağlantıyı aşağıda veriyorum:

    http://www.sadievrenseker.com/c/

    Bu bağlantıdaki 3. ödev ve çözümü size fikir verebilir. Ayrıca ders notlarına bakmanızda da yarar var.

    Başarılar

  8. Şerif Muammer

    Teşekkür ederim, konuyu çözdüm, basit Visual Studio 2010 hataları işimi zorlaştırmış sadece. Bağlantı için ayrıca teşekkürler, iyi çalışmalar.

  9. HasanFatih

    Sadi Hocam merhaba. Bir kez daha e-mail atmıştım Atatürk Üni. Bilgisayar Müh. 1.sınıf öğrencisiyim. C++ Programlama dersi görüyoruz. Hocamızın verdiği bir projede’ki soru’da vermiş olduğu hatayı dünden beri uğraşmama rağmen bulamadım. Bu hata’nın nereden kaynaklandığını ve nasıl çözüleceğini öğrenmek istiyorum. Ne zaman cevap verirseniz farketmez. Önemli olan proje’den alacağım puan değil bu soruyu anlamam gerekli.Proje’nin sorusu resim1 ve resim2’de mevcut. Resim3’de header , Resim4 ve Resim5’de Cpp, Resim6’da ise yürütücü ile birlikte hata’nın resmi mevcut. Sizden cevap bekliyorum. Hasan Fatih KAVİ

    Resim1:
    Resim2:
    Resim3:
    Resim4:
    Resim5:
    Resim6:

  10. Şadi Evren ŞEKER Article Author

    Almış olduğunuz hata, literatürde “uninitialized pointer” şeklinde geçen meşhur bir hata. Genelde bir göstericinin içine değer koymadan (veya gerekli hafıza ayırımı (memory allocation)) yapılmadan kullanılması durumunda alınır. Sizin için satir isimli değişkende bu hatayı veriyor.

    Ne yazık ki elimde macos olduğu ve visual studio yüklü olmadığı için visual studio ile deneyemedim ama kodunuzun “satir” değişkenini ilgilendiren kısımlarını yazıp g++ ile denedim:

    ses3:sadievrenseker$ cat deneme.cpp
    #include 
    using namespace std;
    int main(){
      int satir,sutun;
      cin>>satir>>sutun;
      int **matrisPtr = new int *[satir];
      if(satir==sutun)
        cout < < "deneme";
    }
    ses3:sadievrenseker$ g++ deneme.cpp 
    ses3:sadievrenseker$ ./a.out
    3 3
    denemeses3:sadievrenseker$ 
    

    Yukarıda görüldüğü üzere "satir" değişkenini ilgilendiren kısımda bir hata vermeden çalışıyor. Şimdi sorun visual studio ile ilgili olabilir (programcı hatalarını engellemek için ek koruma kontrolleri bulunuyor) veya ben göremiyor olabilirim. Bu yüzden ilk fırsatta visual studio yükleyip deneyeceğim.

  11. Şadi Evren ŞEKER Article Author

    Diğer dosyalarınıza da baktım ve sanırım hata Resim 5’te. Yani gizemlimatrismi fonksiyonuna satir parametresini vermişsiniz (Fonksiyon1’in ilk iki satırı) ve bu değişkenin değeri bilinmiyor.

    Çözüm olarak Fonksiyon1(int **matrisPtr, int satir) şeklinde tanımlayıp fonksiyon içerisindeki int satir; tanımı yapılan ilk satırı silin. Ardından fonksiyonu çağırdığınız resim6’daki koda, ikinci parametre olarak satir değişkenini ekleyin (nesnePtr->Fonksiyon1(matrisPtr,satir) şeklinde). Büyük ihtimalle çalışacaktır.

    Başarılar

  12. HasanFatih

    Hocam hata ortadan kalktı, programı çalıştırdığımda ise kullanıcı olarak mesela satir için 3, sütun için 3 girdiğimde altta vereceğim resimdeki hata meydana geliyor. Hiçbir değer giremiyorum ve hatayı alıyorum. Birde resim2’deki matris’de herhangi bir satır ile herhangi bir sütunun toplamı M sabitine eşit olmalı. M’nin bağıntısıda resim1’de mevcut. Ben zannediyorum bu toplam’ı yanlış yaptım. Satır toplamını toplam1’e , sütun toplamını ise toplam2’ye yaptım. Görüşlerinizi bekliyorum.

    Hatanın Resmi:

  13. HasanFatih

    Şadi hocam sadece resim2’deki örneği denesek oluyormuş. Yani satır sütun sayısını girmemize gerek yok. Ve de matris içindeki rakamları siyah ekranda değil direk yürütücünün içerisinde yada fonksyonun içerisinde girebiliyoruz. Son haliyle neler yapabilirim.

  14. HasanFatih

    Yalnız eğer sadece resim2’deki örneğe göre soruyu yaparsak soruyu tam yapmış olmuyoruz. Kullanıcı satır ve sütun sayılarını giricek. Matrisin içindeki elemanları biz programı çalıştırdıktan sonra girmek zorundayız. Yani siyah ekran açıldıktan sonra elemanları biz gireceğiz. Onun için çalışıyorum şuan hocam.
    Garip bir hata var düzeltmeye çalışıyorum.

    http://p1305.hizliresim.com/19/9/mw2b1.png

  15. HasanFatih

    CPP KODLARI:

    #include "Hasan_Fatih_KAVİ_Proje_5.h"
    #include 
    using namespace std;
    bool Hasan_Fatih_KAVİ_Proje5::GizemliMatrisMi(int satir,int sutun) //Yardımcı Fonksyon tanımı
    {
    	int **matrisPtr=new int*[satir];//İki boyutlu dizinin satır sayısının deklare edilmesi.
    	int a,b,i,j,k,d;//Kullanacağımız değişkenler
    	int toplam1=0,toplam2=0,toplam3=0,toplam4=0;
    	int M=satir*(satir*satir+1)/2;//Proje'de verilen bağıntı.
    	for(int z=0;z
    

    YÜRÜTÜCÜ KODLARI:

    #include 
    #include "Hasan_Fatih_KAVİ_Proje_5.h"
    using namespace std;
    int main()
    {
    	setlocale(LC_ALL,"Turkish");//Türkçe karakterlerin gözükmesi için
    	int satir,sutun;
    	Hasan_Fatih_KAVİ_Proje5 *nesnePtr=new Hasan_Fatih_KAVİ_Proje5; // Yeni bir pointer deklare ediyoruz.
    	cout<>satir>>sutun;// Kullanıcıdan satır ve sütun isteyip atama işlemini yapıyoruz.
    	int **matrisPtr=new int*[satir];
    	for(int i=0;iFonksiyon1(matrisPtr,satir,sutun)==true)//Tüm şartları sağlayıp geriye true döndürüyor ise
    			return true;//cout< <"Matris gizemli bir matristir.n";
    		else
    			return false;//cout<<"Matris gizemli bir matris değildir.n";
    	else//Kare matris değilse programı sonlandır.
    		cout<<"Lütfen satır ve sütun sayısını eşit giriniz.n ";//return false;
    	delete [] matrisPtr;// Oluşturduğumuz pointerleri silme işlemi.
    	delete  nesnePtr;
    	for(int i=0;i
    

  16. HasanFatih

    Başlık Dosyası(header) KODLARI:

    #ifndef PROJE5_H
    #define PROJE5_H
    class Hasan_Fatih_KAVİ_Proje5 // Sınıf
    {
    public:
    	int Fonksiyon1(int**,int,int); // Fonksiyon
    private:
    	bool GizemliMatrisMi(int,int); // Yardımcı fonksiyon
    };
    #endif
    
  17. HasanFatih

    12.satırdan sonra cin kullanmaya gerek yok.Zaten 12.satırın içinde kullanılması gerekenler kullanılmış.. İstersem 12.satırda kullanmayıp sonra cin ile de atama yapabilirdim.. Sizde görünmüyor olabilir hocam..Ben bir hata buldum şimdi onu düzeltmeye çalışacağım Hocam.

    Yürütücü’de fonksiyon1 3 parametre alıyor bunlardan biride matrisptr. Cpp dosyasında fonksiyon1’in içinde gizemlimatrismi kontrolü yapılıyor sadece. Ama gizemlimatrismi fonksiyonu 2 parametre alıyor ve matrisptr’yi parametre olarak almadığı için herhalde verdi hatayı.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir