PDA

Tam Sürümünü Görmek İçin : Pointers


quasimodo
14/12/2006, 14:22
*p
burada p bir işaretçi *p de işaretçinin işaret ettiği adreste bulunan nesnedir.
Bir yerde şu yazıyı okudum:
Şüphesiz p işaretçisinin kendiside bir nesne olduğu için onunda bir adresi vardır? Bu nedemek anlamış değilim?

int *p;
p = (int *) 0x1FC0;
//burada 1FC0 adresi bellekten bir int değer olarak kullanılmak üzere
//ayrılıp p adresine yollanıyor.

//peki bu ifade yanlış değilmi yada ne demek istiyor?
int *p = (int *) 0x1FC0;

//yine aynı şekilde bu ifadeler ne demek
char *c = s;
float *f = &x;


skate
14/12/2006, 17:02
Sen herhangi bir pointer tanımladığında bu bir adresi gösterirken kendisi de bir adrese yazılır. Dolayısıyla "Şüphesiz p işaretçisinin kendiside bir nesne olduğu için onunda bir adresi vardır" doğru bir ifadedir. Tanımlanan herşey hafızada bir adrese yazılır sonuçta.

Gelelim sorularına:
int *p;
p = (int *) 0x1FC0;

ile
int *p = (int *) 0x1FC0;

arasında hiçbir fark göremiyorum ben. birinde tanımlanıp sonra değer alıyor, ikincide ise tanımlandığı satırda değer alıyor. Burda sen ikincisini ilkine uyarlarsak şöyle olacağı fikrine kapılmış olabilirsin.

int *p;
*p = (int *) 0x1FC0;

Ama asıl bu yanlış (en azından yapılmak istenene göre). Çünkü p ilk satırda zaten pointer olarak tanımlanıyor. İkinci satırda doğrudan "p"yi bir değere işaretlediğimizde point ettiği adres değişecektir.

char *c = s;

s'nin değerini point edeceği adres değeri olarak c pointerına eşitler.

float *f = &x;

f x'e point eder çünkü x'in adres değerine eşitleniyor.

mr1yh1
14/12/2006, 18:15
bende bir örnek vereyim , umarım faydalı olmaktan çok karıştırmaz.

int i = 5;
int* ii = &i;
printf("%d %p \n", i, &i );
printf("%d %p \n", *ii, ii );
printf("%p \n", &ii );


i ve *ii aynı , yani i'nin tuttuğu değer.
&i ve ii aynı , yani i değişkeninin bellek adresi.
&ii ise işte o pointer olarak kullanılan değişkenin ( ii nin ) bellek adresi.

quasimodo
16/12/2006, 14:12
int *p;
p = (int *) 0x1FC0;

ile
int *p = (int *) 0x1FC0;

arasında hiçbir fark göremiyorum ben. birinde tanımlanıp sonra değer alıyor, ikincide ise tanımlandığı satırda değer alıyor. Burda sen ikincisini ilkine uyarlarsak şöyle olacağı fikrine kapılmış olabilirsin.

şimdi
int *p;
diye bir pointer tanımladığımızda. p bir adres *p de o adresin içeriğidir.p = (int *) 0x1FC0;

bu ifadede *p işaretçisinin adresi 1FC0 olarak belirleniyor. Ama
*p = ... dediğimizde o adrese atamak istediğimiz bir değer yazmamız gerekmiyormu? Oysa biz *p = (int *) 0x1FC0; yaparak p adresinin içine 1FC0 diye bir HEX sayı koymuş olmuyormuyuz?

acehreli
16/12/2006, 20:06
quasimodo, basindaki 'int'i kaldirarak


*p = (int *) 0x1FC0;


yazdigin zaman isleri karistiriyorsun. Senin de dusundugun gibi, o zaman hatali oluyor.

Ilk verdigin ornekte basinda bir de int var:


int *p = (int *) 0x1FC0;


Bu ilk verdigin satirda iki sey gerceklesir:

1) p'nin 'int*' olarak tanimlanmasi: "p bir int isaretcisidir"

Ayrinti: Bu kisisel bir konu ama ben isaretci tanimlarinda * isaretinin nesnenin adina yapisik olarak yazilmasini sevmiyorum ve kodumda hic kullanmiyorum. Ben olsam soyle yazardim:


int * p = (int *) 0x1FC0;


Yapisik yazilmasini, "gosterdigi nesne"yi ifade etmek icin kullaniyorum:


// daha sonra bir yerde:
*p = 42;


Boyle olunca kod bana daha okunakli ve daha az karisik geliyor.

2) p'ye ilk deger atanmasi: "p'nin degeri 0x1fc0'dur" ("p, 0x1fc0'daki int'e isaret etmektedir")

Yani ilk yazdigin kodda bir sorun yok. Tanimin yapildigi anda ilk degerin de atanabildigini anlamak gerek. Bunu anladiktan sonra da hep oyle yapmak cok iyi olur... :)

Ornegin ilk kodda p'yi ilk degersiz birakmak yerine onu 0'la (veya NULL'la) ilk degerlemek daha iyidir:


int *p; // <-- KOTU; cunku p'nin degeri belirsiz; yanlislikla kullanirsak HATA!
p = (int *) 0x1FC0;


Tanimladigimiz yerde uygun bir ilk deger yoksa, 0'la ilk degerleriz:


int * p = 0; // * karakterini de ayri yazdim :)
/* ... */
// daha sonra:
p = &bir_int;


Ali

quasimodo
16/12/2006, 22:13
Yani biz ozaman
int *p = 12;
/* yada */
int a;
int *p = &a;
//yani tanımlama işlemini yaparken ildeğerde verebiliyoruz
//ilk adreste
ama başında int olmazsa...

int * p; /* senin dediğin gibi :) */
*p = 12;
// yada
int a;
*p = a;
/* vede */
p = &a;
p = (int *) 0x10FC;
sadece işlemlerini yapabiliyoruz. Doğru anlamışmıyım?

shurzan
17/12/2006, 00:53
Yalnış anlmışsın!
Çünkü Pointer'ın ilk değeri ya bir bellek adresi olmalı ya NULL olmalı, pek doğru olmasada yada 0 (sıfır değişmezi) olmalı eğer bir dizge değilse değişmez olmamalı yani verdiğin şu satırda pointer henüz bir nesneyi işaret etmezken,

int * p; /* senin dediğin gibi :) */
*p = 12;

değişmez değer atanmaz.
Ayrıca şu yazdığında doğru değil

// yada
int a;
*p = a;

Bunu yapmakla p pointeri halen bir bellek adresi göstermezken a nın içeriğini ( adresini değil) p nin işaret ettiği bellek bölgesine atamaya çalışmaktasınki bu yalnış!

shurzan
17/12/2006, 01:59
Sevgili arakadaşım vbmenu_register("postmenu_258016", true); quasimodo;
Yazdıklarından anladığım içerik (*) ve adres (&) operatörlerinin nasıl kullanıldığına dair biraz sıkıntın var konuyu biraz açmak isterim.
Şöyleki;
int *p;
ile biz bir int türünde nesneyi gösterebilecek göstericiyi derleyeciye bildiriyoruz.
Şunu yapmakla ise,
int *p = (int *) 0x1FC0;
Derleyiciye, int türünde bir nesneyi gösteren bir göstericimizi ve aynı satırda bu göstericinin gösterdiği 1FC0 bellek adresinede sahip olduğunu kendi adresi değil göstereceği adresi kendisinde barındırdığını bildirmiş oluruz.

Ancak Ali hocanın belirttiği konu şu,
int *p;
dediğimizde pointer sahip olduğu değer bir artık değer olacaktır olaki kazara kullanılmak istenirse hiçte erişmek istemdiğimiz bir adresi gösterecektir o yüzden bir pointer tanımladığımızda mutlaka ilk değerini atamalıyız önceki mesajımda da belirttiğim gibi yaratılırken ilk değeri ya bir bellek adresi olmalı ya NULL olmalı ya da 0 olmalı
en doğrusu,
int *p=NULL;
olmalı. Bundan sonra
int a;
diye bir değişkenimiz varsa ve p pointericimiz ile ona erişlmek isteniyorsa
p=&a;
şeklinde anın bellketeki adresini p pointerine atayabiliriz. Dikkat ettiysen p nin önüne (*) içerik operatörünü koymadık çünkü p nin sahip olacağı değer a nın adresi olacaktır eğer & (adres) operatörünü koymasaydık a'nın adresini değil a'nın sahip olduğu integer değerini atamış olacaktık bu yalnış olurdu.

Bu aşamdan sonra eğer a'nın içeriğne p ile erişlmek istendiğinde içerik operatörünü kullanacağız şöyleki,
printf("%d", *p);
bu şekilde anın içeriğini okuyabiliriz ya da
*p = 2006;
atamsı yaparsak aslında a'ya atama yapmış oluruz a artık 2006 değerine sahip olacaktır.

daha sonraları
int b = 2007;
*p = b;
yazdığımızda aslında a nesnesine b nin sahip olduğu 2007 değerini atamış oluruz p pointerinin gösterdiği adresi değiştirmiş olmayız.
Konuyu daha iyi anlaman için biraz daha ilerleyelim
şimdide p pointeri artık b yi göstersin,
p = &b;
pointer artık b'yi gösteriyor ve bir yerlere geldik a artık başka bir değere sahip mesela 2010 integer değerine sahip olsun ve,
*p = a;
atamsı yaptığımızda a'nın adresini değil a'nın içeriğini yani 2010'u atamış olduk
artık b 2010 değerine sahip olacaktır.

Sorduğun şu soruya da,//yine aynı şekilde bu ifadeler ne demek
char *c = s;
float *f = &x;
şu demek oluyor,
pointer'ler göstereceği nesne türünden olmalı nedeni ise göstereceği nesnenin boyunu bilbilecek bilgiye sahip olmalı yani,
char *c = s;
ile char türünden bir diziyi gösteriyor çünkü dizilerin adı aynı zamanda dizinin adresidir yani s önüne adres operatörünü koymaya gerek yoktur ve
c pointer'i bu atamayla s dizisinin ilk dizi elemanını gösteriyor ve bu ilk dizi elamanı char olduğundan 1 byte tır pointer bunu biliyor 1 byte'tan sonra bir sonraki dizi elamnını göstereceğinide biliyor.

şimdi,
float *f = &x;
ile f pointer'i yaratılıyor ayrıca float türünde x değişkeninin adreside atanıyor f pointeri biliyorki x'in bellekte kapladığı alan 4 byte dir yani bu bellek adresine eriştiğinde nereden başlayacağını nerde biteceğini iyi biliyor.

Bundan sonra dipeceksinki pointer kendisinin boyutu nedir ve bellekte nerede bulunur.
C ve C++ ta tüm pointerler 4 Byte'tır adresinin ne olduğunu arkadaşım Mr1yh1 satırlarında belirttiği gibi,

printf("%p \n", &p );
p nin bellek adresini görebilirsin.

Uzun bir açıklma oldu umarım konuyu kavramanda yardımcı olmuşumdur.
Başarılar.

quasimodo
17/12/2006, 17:46
int *p;
dediğimizde pointer sahip olduğu değer bir artık değer olacaktır olaki kazara kullanılmak istenirse hiçte erişmek istemdiğimiz bir adresi gösterecektir o yüzden bir pointer tanımladığımızda mutlaka ilk değerini atamalıyız önceki mesajımda da belirttiğim gibi yaratılırken ilk değeri ya bir bellek adresi olmalı ya NULL olmalı ya da 0 olmalı
int*p = NULL;
/* yada */
int* c = 0;
ne yapmış oluyoruz ? ÇÜnkü

int* p = NULL;
printf("%p\n",p);
printf("%d",*p);
//dediğimde program kitlendi...ama
int* p = NULL;
int a;
p = &a;
printf("%p\n",p);
printf("%d",*p);
//program çalıştı..int* p= NULL; dediğimizde neye ilk değer veriyoruz???

quasimodo
17/12/2006, 17:56
int* p;
dediğmde;
bellek bana bir int türünde adres ve içinde rastgele bir sayı veriyor.
Peki ben neden
int* p;
*p = 12;
//deyip neden içeriğini değiştiremiyorum da.

int* p;
int a;
p = &a;
*p = 50;
//diyice içeriğini değiştirebiliyorum.

Çünkü Pointer'ın ilk değeri ya bir bellek adresi olmalı ya NULL olmalı, pek doğru olmasada yada 0 (sıfır değişmezi) olmalı eğer bir dizge değilse değişmez olmamalı yani verdiğin şu satırda pointer henüz bir nesneyi işaret etmezken, değişmez değer atanmaz.

cümlesini anlamis degilim...

Sabahi
18/12/2006, 09:09
@quasimodo
int *p; seklinde bir pointer deklare ettiginizde p rastgele bir sayi icermiyor fakat hafizada rastgele bir adrese isaret ediyor. Eger p gecerli bir adrese isaret etmeden *p = 12; gibi bir atama yaparsaniz buyuk bir ihtimalle hafizada yazma hakkiniz olmayan bir adrese ulastiginiz icinde hata aliyorsunuz.

int *p; // p hafizada rastgele bir adrese isaret ediyor.
int a;
p=&a; // p a degiskenin hafizadaki adresine isaret ediyor ve artik gecerli.
*p=50; dediginizde ise degistirdiginiz p nin icerigi degil, a degiskeninin degeri.

Çünkü Pointer'ın ilk değeri ya bir bellek adresi olmalı ya NULL olmalı
Yukarda bahsettigimiz rastgele hafizaya yazma ihtimalinden kacinmak icin genel olarak turu pointer olan bir degisken deklare edildiginde ilk is
int *p = NULL; gibi bir atama yapariz.
Soylemek istedikleri bu yanilmiyorsam.

shurzan
18/12/2006, 15:20
Çok doğru Sabahi zaten bunu sen biliyorsun ancak arkadaşa yardımcı olmak için yukarıda konuyu uzunca ayrıntılı açamama rağmen halan anlamakta zorlanıyor son sordukları verdiğim açıklamada vardı ama genede cevaplamaya çalışayım.

Sorduğun,

int*p = NULL;
/* yada */
int* c = 0;
ne yapmış oluyoruz ? ÇÜnkü...

//SHURZAN
Bellekte int türününde bir nesneyi gösterebilecek gösterici yaratmış oluyoruz ve NULL atayarak bir adres ataması yapılana kadar hiç bir bellek erişimi yapmamsını sağlıyoruz

int* p = NULL;
printf("%p\n",p);
printf("%d",*p);
//dediğimde program kitlendi...ama

//SHURZAN
Tabi kilitlenir çünkü ikinci printf ile ekrana pointerin gösterdiği bellek adresindeki veriyi okumaya çalışıyorsun peki pointerimiz hangi bellek adresini gösteriyor? Hiçbir bellek adresini göstermiyor çünkü NULL atadık!

int* p = NULL;
int a;
p = &a;
printf("%p\n",p);
printf("%d",*p);
//program çalıştı..int* p= NULL; dediğimizde neye ilk değer veriyoruz???

//SHURZAN
Hala anlamadın mı neden ilk değeri atamamız gerektiğini?
ama şunuda yapabilrdin
int a;
int *p=&a;
//...

Gördüğün gibi pointeri yaratırken ilkdeğer olarak a'nın bellek adresini atamış olduk.



int* p;
dediğmde;
bellek bana bir int türünde adres ve içinde rastgele bir sayı veriyor.
Peki ben neden

Kod:
int* p;*p = 12;//deyip neden içeriğini değiştiremiyorum da.
//SHURZAN
bu atamayla neyi değiştirmeye çalışıyorsun p pointeri gösterebilecek bir adrese sahip mi ki sen o adrese erişiyor ona 12 değerini atamaya çalışıyorsun
Sanırım sen şunu anlmadın göstericiler diğer değişkenler gibi düşünmen yani int türünde bir değişkene değer atandığı gibi göstericiyede değer atama çalışman
Hayır göstericilere sadece bellek edresi ve NULL atanabilir 12 gibi bir değer atanamaz
Kod:
int* p;int a;p = &a;*p = 50;//diyice
//SHURZAN
Sen burada pointer'in içeriğini değil gösterdiği a'nın içeriğini değiştiriyorsun
Bunuda yazmıştım aslında.


Çünkü Pointer'ın ilk değeri ya bir bellek adresi olmalı ya NULL olmalı, pek doğru olmasada yada 0 (sıfır değişmezi) olmalı eğer bir dizge değilse değişmez olmamalı yani verdiğin şu satırda pointer henüz bir nesneyi işaret etmezken, değişmez değer atanmaz. cümlesini anlamis degilim...

//SHURZAN
Bende sorundan bir şey anlamış değilim çok mu karmaşık anlattım?


int* p = NULL;int a;p = &a;printf("%p\n",p);printf("%d",*p);//program çalıştı..int* p= NULL; dediğimizde neye ilk değer veriyoruz???
//SHURZAN
p adında int türünde bellekteki nesne adresini gösterebilecek pointer'a
yani pointer hiç bir adres göstermemiş olur.

Tabi çalışır çünkü pointer ilkdeğer olarak NULL atansada sonraki satırda p pointer'a a'nın adresi atanmış ve artık a'nın bellekteki adresini gösterebiliyor "*p" yani içerik opretörüyle okunmaya çalışıldığında gösterdiği nesneye erişirsiniz.


ve Lütfen yazılanları tekrardan gözdengeçir sordukların zaten yukarıdaki açıklamalarda zaten vardı
Basit bir konuda bu kadar takılma yapma.
Başarılar...

mr1yh1
18/12/2006, 17:34
@quasimodo
bence önce bu klasik satırı yorumla.
int* ii = new int();
new ile, ii ye bellek ayırdık.
........
burada ise zaten i için ayrılmış olanı kullanıyoruz.
int i;
int* ii = &i;
.

quasimodo
19/12/2006, 15:41
Sabırla vermiş olduğunuz cevaplardan dolayı teşekür ederim. Umarım

quasimodo
19/12/2006, 15:42
Sabırla vermiş olduğunuz cevaplardan dolayı teşekür ederim.

acehreli
19/12/2006, 20:13
Ben de bir kac kisa hatirlatma yapayim. Kucuk bir sozluk:

1) Yildiz isareti (*): Isaretcilerle birlikte iki anlamda kullanilir:

a) Kendisinden once bir tUr adi bulundugu durumda, kendisinden sonra gelenin o tUrU gosteren bir isaretci oldugunu bildirir:


bir_tUr * bir_isaretci;
/*
Anlami: "bir_isaretci, bir_tUr tUrUnden nesneleri gosterebilen bir isaretcidir."
*/


b) Kendisinden once bir tUr adi bulunmadigi durumda, kendisinden sonra yazilan isaretcinin gosterdigi nesneye erisim saglar:


printf("%d", *p);
/*
Anlami: "p'nin gosterdiginin degerini yazdir"
*/

*p = 42;
/*
Anlami: "p'nin gosterdigi int'in degeri 42 olsun"
*/

int i = *p + 7;
/*
Anlami: "i bir int'tir; ilk degeri, p'nin gosterdigi int'in degerinin 7 fazlasidir"
*/



2) VE isareti (&): Kendisinden sonra bir nesne kullanildiginda, o nesnenin adresini verir:


printf("%p", &i); // Not: %d degil, %p kullandik
/*
Anlami: "i'nin adresini yazdir"
*/

int * p = &i;
/*
Anlami: "p bir int isaretcisidir; ilk degeri, i'nin adresidir"
Yani: "p bir int isaretcisidir; i'yi gostermektedir"

Not: Bir isaretciye bir nesnenin adresini atamak, o isaretcinin o
nesneyi gostermesini saglamak anlamina gelir.
*/


Bunlari bir program icinde de kullanacagim. Her ne kadar soru C olsa da ben nesneleri C++'in izin verdigi sekilde yerleri geldikce tanimlayacagim:


#include <stdio.h>

int main()
{
int * p;
/*
Anlami: "p bir int isaretcisidir"

Hangi int'i gosterdigini soylemedigim icin p'yi
kullanamam. Calistigim ortamda p'nin rastgele bir degerinin olup
olmadigini tartismaya bile gerek yoktur. p'nin hangi int'e isaret
ettigini soylemedigim icin p'yi kullanamam. O kadar basit... :)
*/

int i = 42;
p = &i;
/*
Anlami: "p i'yi gostermektedir".
*/

int j = 7;
p = &j;
/*
Anlami: "p j'yi gostermektedir".
*/

printf("p'nin gosterdiginin (j'nin) degeri 7: %d\n", *p);
/*
Anlami: "p'nin gosterdigini yazdir".
*/

*p = 8;
/*
Anlami: "p'nin gosterdigini 8 yap".

Bu noktada p'nin gosterdigi j oldugu icin j'nin degeri 8 olur.
*/
printf("\nj'nin degeri artik 8: %d\n", j);
printf("baska deyisle; p'nin gosterdigi artik 8: %d\n", *p);

int * q = NULL;
/*
Anlami: "q hicbir seyi gostermeyen bir int isaretcisidir".

Dikkatli bir programci olarak onun bu noktada hicbir int'i
gostermedigini acikca belirtmek icin degerini NULL yaptim. (NULL bu
baglamda 0 ile ayni anlamdadir: "int * q = 0;" da yazabilirdim.)
*/

q = p;
/*
Anlami: "q p ile esdegerdir; yani artik q da p'nin gosterdigini gostermektedir."
*/

printf("\nq da j'yi gosterir (gosterdigi 8 olmali): %d\n", *q);

int * r = &i;
/*
Anlami: "r bir int isarecsidir ve hayatina i'yi gostererek baslamaktadir."
*/

printf("\nr'nin gosterdigi deger 42 olmali: %d\n", *r);
printf("(cunku i'nin degeri 42: %d)\n", i);

return 0;
}


Ali