Tam Sürümünü Görmek İçin : Kapanmıyor.
nilsonmandela
25/07/2005, 12:04
Merhaba.Yazdığım bir kodu derlediğimde program doğru çalışıyor.Fakat bir tuşa bastığımda kapanması gerekirken hata veriyor ve program kapanmıyor.Malesef kodu buraya yazamıyorum.Yardımcı olursanız sevinirim.Tşkrler.
nilsonmandela
25/07/2005, 16:23
sesimi duyan yokmuuu?
Fakat bir tuşa bastığımda kapanması gerekirken hata veriyor
Sebebi herhangi birsey olabilir. Bu kadar az bilgi verirsen kimse sana cevap vereMEZ.
nilsonmandela
25/07/2005, 16:44
keşke verebilseydim :(
Butonun yaptigi islemleri try catch blogu icine koy, muhtemelen bir exception atiliyordur. Ne atildigini buraya yazabilirsin sanirim.
nilsonmandela
25/07/2005, 18:15
#include <iostream>
#include <conio>
#include <cstring>
int main()
{
char* a;
char* b;
int k=0;
int n=0;
char temp;
cout<<"Virgullerle ayrilmasini istediginiz sayiyi giriniz fakat '.'"
"kullanmayiniz(programi fazla zorlamayalim:)\n\n";
cin>>a;
for(int i=strlen(a)-1;i>=0;i--)
{
b[k++]=a[i]; //birbirine esitleniyor
n++;
if(!(n%3))
b[k++]=','; //virgul konuluyor
}
if(b[k-1]==',')
b[--k]='\0';
else
b[k]='\0';
for(int i=0;i<k/2;i++) //ters cevriliyor
{
temp=b[i];
b[i]=b[((k-1)-i)];
b[((k-1)-i)]=temp;
}
cout<<"\nSayinin virgullerle ayrilmis hali:"<<b<<endl;
getch();
return 0;
}
acehreli
25/07/2005, 18:45
nilsonmandela,
1) Anladigim kadariyla, giristen gelen karakterleri cin >> a satiri ile a'nin gosterdigi bellek alanina almaya calisiyorsun. Peki a nereyi gosteriyor?
a'nin degeri hic verilmedigi icin, icinde cop bir deger oldugundan, bellegin sana ait olan bir yerini gostermiyor.
2) a gibi anlasilmaz adlar kullanma; programin anlasilmasi cok guc oluyor
3) cin, cout, vs. gibi adlari kullanmadan once programin basina en azindan bir
using namespace std;
satiri eklemen gerekiyor.
4) Bir satira basildiginda programdan cikma isinin bu programla bir ilgisini kuramadim. <conio> basligini eklemenin veya getch()'yi cagirmanin bu programla bir ilgisi gercekten de yok.
Eger yasadigin sorun, bir gelistirme ortami (IDE) icinden calistirdiginda program penceresinin ucup gitmesi ise, cozumu cok basit: programini gelistirme ortami icerisinden calistirma. Bir komut satiri penceresi ac, programin icinde bulundugu dizine git, ve programini orada calistir. Boylece daha onceki sonuclari filan da ekranda gorebilirsin.
Ornegin su anda bilgisayarimdaki bir DOS penceresi icinde
C:\Dev-Cpp\Projects\Deneme>
dizinindeyim. Seninki gibi programlari derleyip o pencere icinde ust ok tusuna basip Enter yaparak calistiriyorum.
Ali
nilsonmandela
25/07/2005, 19:13
Görüşleriniz için teşekkür ediyorum.Fakat aslında tek problemim bu değil.Programı geliştirmek amacıyla yaptığım herşeyde derleyici aynı hatayı veriyor ve bu defa programı çalıştırmak zahmetinde de bulunmuyor.Karekter katarlarını başka şekillerde de tanımlasam sorunu çözemedim.Neyse en iyisi daha fazla ısrar etmeyeyim.Bu arada anlaşılmaz işaretçi isimleri için kusura bakmayın.Kodu aceleyle tekrar yazdığım için böyle oldu :none: Tekrar teşekkür ediyor iyi çalışmalar diliyorum.
acehreli
25/07/2005, 23:23
Aslinda a'daki sorun b'de de var. Program o yuzden gocuyordur. C dizileri yerine C++'in std::string turunu kullanirsan bu tur sorunlarla karsilasmazsin.
Ali
kullandığın char *a ve char *b, derleyiciye diyorki :
a ve b , bellekde, içinde char tipi veri olan bir adresi tutuyor...
mesela a = 1000 ise 1000. numaralı adreste 1 baytlık char verisine işaret eder a ... ( virtual memory :aglama: ?? )
peki değerleri ne ? yani bellek adresi neresi ?
göstermemişsin..
bu gibi durumlarda şanslı isen hemen hata alırsın..
bunu doğru şekilde yapmanın iki yolu vardır..
------birincisi static olan
char *d = "denemeler";
char *a = d;
yani önceden statik olarak ayrılmış bir bellek bölgesine işaret edeceksin bu bellek miktarı derleme zamanında belirlenir.. ve onun sınırlarını aşmamak zorundasın.
yani yukarıdaki a için a[9] yok..olmamalı...
aksi taktirde başka birşey için kullanıllan belleğe yazarsın..
( 9. '\0' karekteri var... 10. ise tümüyle a ile alakasız ..
mesela 9. yu değiştirisen cout<<a yazdığında başın belaya girer..)
---ikincisi yol dinamik olan:
8 in olduğu yerde bir değişken de olabilir.. bu bellek çalışma zamanında ayrılır...yine aşmaman lazım...
char *a = new char[9];
a[0] = 'd' ;
a[1] = 'e' ;
...
a[7] = 'r' ;
a[8] = '\0' ; //null terminated string yaptık onu..
null terminated yapmazsan cout<<a; yı kullanamazsın...
acehreli
26/07/2005, 13:14
mr1yh1, ilk gosterdigin yol yanlistir cunku "denemeler" gibi derleme zamani dizgileri sabittirler. Onlarin turu aslindan 'const char *'dir (veya 'char const *'; ayni sey). Oyle olmalarina ragmen 'char *' ile gosterilebilmeleri tarihsel nedenlerden dolayidir.
Eskiden C'de de olsa, programin sabit bellek alani olarak kabul edilirler ve degistirilmeleri durumunda tanimsiz davranis olusur. (Linux ortamlarinda hemen bir calisma zamani hatasi olusur.)
Dizgi sonlandirma karakterinde de dilin surcmus. Iki yerde '\0' yerine '\n' yazmissin. :)
new char[8] yaptiktan sonra da dizi disina '\n' karakteri koyuyorsun. Sekiz elemanli dizi elemanlari [0,7] araligindadir.
Ali
'\n' leri değiştirdim.. ciddi hata yapmışım..
"denemeler" i 9 değil 8 saymışım ikincide onuda değiştirdim..
sağolasın ..:hey:
mr1yh1, ilk gosterdigin yol yanlistir cunku "denemeler" gibi derleme zamani dizgileri sabittirler. Onlarin turu aslindan 'const char *'dir (veya 'char const *'; ayni sey). Oyle olmalarina ragmen 'char *' ile gosterilebilmeleri tarihsel nedenlerden dolayidir.
bu kısmı anlamadım..
char* a = "denemeler";
ve
const char* = "denemeler";
aynı şekildemi yorumlanıyor ? ( ikisi de const )
yoksa linux da ilkini tanımlamaya mı izin verilmiyor ?
bendeki gcc bunu kabul ediyor ( hiçbir uyarı dahi vermiyor)
@nilsonmandela
yukarıdaki statik yöntem için diğer yol..
char a[9];
char *b = a;
acehreli
26/07/2005, 14:45
Programi icine "denemeler" gibi yazilan dizgiler sabittirler.
char * a = "denemeler";
a[0] = 'D'; // <--- tanimsiz davranis
'char *' ile gosterilebiliyor olmasi, eski C'de buna izin verildigi icin, ve o programlarin C++'ta da derlenebilmeleri icindir. Yani aslinda yukarida yazdigim ilk satir yanlis, ama goz yumulan bir durumdur. Ne olursa olsun, a'nin gosterdigi yerdeki karakterler degistirilemezler.
Derleyiciden yardim alabilmek icin o tur dizgileri yeni yazilan programlarda her zaman icin 'char const *' olarak yazmamiz gerekir. Ancak o zaman derleyici hatasi aliriz:
char const * a = "denemeler";
a[0] = 'D'; // <--- derleme HATAsi
Ali/
"tanımsız davranış" demeni anlayamıyorum..
C++ bütün bellek kontrolünü derleme zamanında yapıyor..
yani derlerken kesinlikle const char* yi char* ye dönüştürmeye izin vermez..
hadi verdi diyelim , eski bir header kullanınca bile uyarı veriyor da , neden bunun için uyarıda bulunmuyor ? ( extra warnings bile açık..)
bu bellek bölgesine yazmak nasıl bir problem çıkarabilir ?
acehreli
26/07/2005, 15:17
"denemeler" gibi derleme zamani dizgileri sabittirler. Dil bunu boyle tanimlar. Onun icindeki karakterleri degistirmek tanimsiz davranistir. Bazi ortamlarda degisebilir, bazi ortamlarda program gocer, daha baska ortamlarda baska sonuclar ortaya cikabilir.
Bunu daha baska nasil soyleyebilecegimi bilemiyorum. O tur bir dizginin icerigi sabittir iste...
Boyle dizgileri programlarimizda uyari bile almadan 'char *' ile gosterebiliyor olmamiz, tarihsel nedenlere dayanir. Her ne kadar dizgi sabitse bile, derleyicilerin onlari 'char *' ile gostermemize izin vermeleri gerekir. Bu, eski programlarin bile yeni derleyicilerle derlenebilmeleri icin gerekmektedir.
Yeni programlarda o tur dizgiler 'char *' ile degil, 'char const *' ile gosterilir. (Ornegin ben oyle yaparim.)
Ama ne olursa olsun, eski programlarda bile o tur dizgilerin icerikleri sabitti. O zaman bile a[0] = 'D' gibi bir ifade tanimsiz bir davranisti. Cunku sabit bir karakteri degistiriyorduk.
Ali
acehreli
26/07/2005, 15:19
Ek olarak: Son sordugun soruya yanit vermeyi unutmusum... Bu bellek bolgesine yazmak, programin gocmesi gibi bir sonuc dogurabilir. Ornegin, Linux uzerinde gcc ile durum da boyledir. Cunku o derleyici, oyle dizgileri "sabit olduklari icin" degistirilemez bir bellek bolgesinde olusturur. a[0] = 'D' gibi bir ifade de programin calisma zamaninda gocmesine neden olur.
Ali
nilsonmandela
26/07/2005, 15:46
mr1yh1,Onlarin turu aslindan 'const char *'dir (veya 'char const *'; ayni sey).
Ali
const* char ve char const* farklı şeyler değilmiydi.Yani biri belleğin içindekinin diğeri ise adres in değişemiyeceğini göstermiyormu?Ayrıca birşeyi daha merak ediyorum.Bir işaretçiye ilk değer vermemek işaret edebileceği yerler açısından tehlike oluşturabiliyor ama sanırım bu genel bir durum değil yani öyle olsaydı herbir değişkene kodu yazmaya başlarken bir ilk değer vermek zorunda kalırdık öyle değilmi?Bir soru daha : Derleyici işe yaramayan yani kullanılmayan bir adres değerini oluşturulan işaretçilere veremezmi(şimdi ya da gelecekte:))
http://www.possibility.com/Cpp/const.html
bunu buldum ve şaşırdım...
quote from the language standard: literal strings don't have to be distinct. This means that it is legal for implementations to use string pooling, where all equal string literals are stored at the same place.
olay derleyicilerin string literalleri aynı olmaları durumunda( mesela iki tane "deneme" farklı değişkenlere atanmış ) , aynı bellek bölgesine yerleştirebilmesi ile ilgili imiş.. string spooling deniyormuş buna ..
VC++ bunu aktif getirmek ya da devre dışı bırakmak için /GF opsiyonuna sahipmiş..
This appears to be an inconsistency in the language standard. A lot of these inconsistencies exist because older C and C++ code would break if the standard were strictly consistent. The standards people are afraid to break old code, because it would mean a decrease in the popularity of the language.
uyarı vermemesini hala anlamıyorum, uyarı vererek de derlemeye devam edebilirdi... :sus:
Bir işaretçiye ilk değer vermemek işaret edebileceği yerler açısından tehlike oluşturabiliyor ama sanırım bu genel bir durum değil yani öyle olsaydı herbir değişkene kodu yazmaya başlarken bir ilk değer vermek zorunda kalırdık öyle değilmi?..
ilk değer vermediğimizde değil, ( initialize )
bu durumdaki işaretçiyi kullandığımızda başımız ağrıyor..
bunun için, hemen ilk değer verilemeyen durumlarda NULL a eşitleme öneriliyor..
bunun faydası NULL a eşitlenmiş bir işaretçiyi kullanmaya kalkarsan olay büyümeden , hemen hata alırsın ...
char *a = NULL;// garantileme yapıldı..
...
a = &b[0] ; // b dizisine işaret ediyor..
ama sanırım bu genel bir durum değil yani öyle olsaydı herbir değişkene kodu yazmaya başlarken bir ilk değer vermek zorunda kalırdık öyle değilmi?
int ix; // "undefined behaviour" isaretciye gore basa daha az bela aciyor ancak yine de bu sekilde belirtilmis.
ama sanırım bu genel bir durum değil yani öyle olsaydı herbir değişkene kodu yazmaya başlarken bir ilk değer vermek zorunda kalırdık öyle değilmi?Kendi yazdığın sınıflar için uygun Ctor u tanımlarsan gerek olmaz...
Bu arada mr1yh1, bende msvc 7 de hata veriyor (runtime da).. Hatta /GF kullansamda kullanmasamda..
uyarı vermemesini hala anlamıyorum, uyarı vererek de derlemeye devam edebilirdi...İşte bu yüzden const char * yapmalısın.. o zaman doğal olarak derleme anında alıyoruz hatayı.. bu da zaten bizim işimize gelen şey (derleme anında hata almak)..
birde const char * ve char const* olayına gelirsek.. normalde önceleri okunabilir olsun diye ikincisini tercih ediyordum ( char const * const * const * const armut vs vs).. belki vc++ a aşina olanlar bilirler.. derleme anında herhangi bi yerde hata varsa, bazen vc++ hiç alakasız hataları da gösteriveriyor.. Yine böyle bi durumda, bu kullanım için "anachronic" kullanım falan diyordu.. hata mesajını tam hatırlamıyorum ama böyle bi mesaj aldım.. daha sonra hiç karşılaşmadım ama yine de ben artık const char * ı tercih ediyorum..
...
İşte bu yüzden const char * yapmalısın.. o zaman doğal olarak derleme anında alıyoruz hatayı.. bu da zaten bizim işimize gelen şey (derleme anında hata almak)..
...
eğer const olarak declare edersem tabii ki hata alırım..
ama sadece string literali değil, integer değerini de const olarak gösterirsem değiştiremem..
const int a =1;// program içinde değiştiremem...
mesele birşeyi yapmanın legal bir yolu varken ( const char *a = "deneme")
var olan sentaxa "gizli anlamlar" yüklemenin saçmalığı..
bu arada hala a[0]='D' nin programı çökerteceğine inanmıyorum, bir neden göremiyorum..
bu bir bellek bölgesine farklı referansların işaret etmesi ve bunlardan birinin bu bellek bölgesini değiştirmesi gibi gayet makul bir eylem....
problemin nedeni bence block copy yapan C fonksiyonları ...
strcpy ya da memcpy gibi.. çünkü bunlar source ve destination için overlap istemiyor ( bellek bölgeleri kesişmemeli )... ve tanımları gereği source const char * olarak tanımlanmış.. yani tam bir belirsiz durum....
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
C++ bu cingözlüğü yapıyor.. bu durumda tabii ki const a* ="deneme" mecburen yazıcaz artık..
const olmasını istemediğimiz değişkenler için bile mecburen yazıcaz, çünkü C++ bize optimizasyon yapmak istiyor.. biz istemesek de istiyor.. ne denebilir..
bence "armut" nin const char * olması çok mantıklı çünkü eğer öyle olmasaydı strcat("armut", "elma"); gibi şeyler yasal olurdu.. bu ve bunun gibi şeyler mantıksız olabildiğini görebiliyoruz (cunku armut sabit ve biz ona ekleme yapmak istiyoruz)..
gcc buna sesini çıkartmıyor (işte bu strcat() de sesini cıkarmaması garip, cunku const char * dan char * donusum kabul ediliyor)... ama çalıştırdığımda linux "Segmentation fault" diyor..
(
Parantez acalım : strcat() in deklarasyonu şöyle :
char * strcat ( char * dest, const char * src );
)
eğer const olarak declare edersem tabii ki hata alırım..
ama sadece string literali değil, integer değerini de const olarak gösterirsem değiştiremem..
const int a =1;// program içinde değiştiremem...acemiyiz dediysek o kadar da deil 8).. o kadarını biliyorum yani 8).. anlatmaya calıstıgım, böle yaparsak hatayı derleme anında farketmis oluruz ( zaten o cumlede dogal olarak demisim).. bu da bizim işimize gelen bişi..
@sckz bunları çok iyi bildiğini biliyorum,
onu söyleme nedenim , zaten dil bu imkanı veriyor const char* ile, neden char* için üstü kapalı hale getirmişler ki ?
bir örnek hazırlarken bir tuhaflık ile karşılaştım..
amacım derleme zamanı dışında const, privatin anlamlı olmadığını göstermek idi.. ( C nin doğrudan bellek erişimi fantazisi.. )
private den istediğim sonucu aldım..fakat const beni şaşırttı...
#include<iostream>
using namespace std;
class A
{
public:
A() { c = 'A';}
char get_c() { return c; }
private:
char c ; // a burada private
};
class B
{
public:
B() { c = 'B';}
char get_c() { return c; }
char c ; // b public
};
int main()
{
const int i = 12;
int *p = (int*) &i; //bellek adresleri ayni olsun
*p = 13; // ok..
cout<< &i << " " << p << endl; // bellek adresleri ayni
cout<< i << " " << *p << endl; // degerler farkli ???
//*****************private ihlali*******
A a;
B *b = new B();
//a yi, b nin kopyasi yaptim..
strcpy( (char*) &a, (const char*) b);
//yani private olan kisma yazdim..
cout << a.get_c() << endl; //a.c = 'B' :)
//******ilk kisimdaki degerleri tekrar kontrol ediyorum
cout<< i << " " << *p << endl; // degerler şimdi daha da farkli !!!!
}
sabit in değiştirme ile ilgili şunları söyleyebilirim : derleyici sabitin kendi degeri yerine sabitin baslangıc degeri atayıcısını kullanıyor.. bu yüzden sabitin degeri sonradan degistirilse bile cıkış degeri 12 oluyor... *p ise gösterilen yerde yazan gerçek deger..
private olayına gelince.. onlar derleme zamanında önemli... bende bi örnek vereyim :
#include <iostream>
using namespace std;
class Base
{
public:
virtual void armut()
{
cout << "Base";
}
};
class Derived : public Base
{
private :
void armut()
{
cout << "Derived";
}
};
int main()
{
Base * myPtr = new Derived;
myPtr->armut(); // Derived::armut() private oldugu halde sorunsuzca erisiyorum..
}
ikinci i ve *p degerlerini ekrana yazdıgında *p nin degisik yazıyor.. cunku adreslerini de tekrar ekrana yazdırdıgımda p baska bi yeri gosteriyo du.. bendeki sonuçlar :
0xbffff1d0 0xbffff1d0
12 13
B
0xbffff1d0 0xbffff100
12 1074694600
ha bu adres nası degisti ? biraz düsünmem gerek...
visual studio da watch ile incelediğimde, ne oluyorsa strcpy() satırında oluyor.. bu satır işletildikten sonra p nin degeri degisiyor..
tabi ya.. iyi de bu fonksiyon (strcpy()) '\0' karakterini bulana kadar kopyalama yapmıyor mu.. dolayısıyla b nesnesinde de böle bişi yok..
B nin Ctor undaki
c = 'B'; satırını c = '\0'; ile degistirince p nin degerine bisi olmuyor..
ve sonuc bekledigimiz gibi oluyor..
birde a nesnesi için en başta bellek ayrılıyor.. tanımlandığı yerde ise, Ctor cagrılıyor.. ( ben visual studio nun yalancısıyım.. kodu adım adım ilerlettiğimde daha main() baslar baslamaz watch ta adresini gorebiliyorum (const int i den once)) (herhalde C deki degiskenlerin en basta durması gerektigi olayı).. (bunun konuyla alakasını mı merak ediyorsunuz.. a, i den once tanımlandıgından dolayısıyla adresi i den once ve bu yuzden p nin degerini degistirebiliyor..)
Not : forumda bi yerde okudum.. sanırım bu pointer dediğimiz zımbırtılar.. sadece adresten ibaret diil.. process ID leri farklı olan, adresi aynı olan degiskenler olabilir.. bu da pointerların sadece adres tutmadığını gösteriyor.. sacmalıyorsam uyarın ?..
tabi ya.. iyi de bu fonksiyon (strcpy()) '\0' karakterini bulana kadar kopyalama yapmıyor mu.. dolayısıyla b nesnesinde de böle bişi yok..
B nin Ctor undaki
c = 'B'; satırını c = '\0'; ile degistirince p nin degerine bisi olmuyor..
ve sonuc bekledigimiz gibi oluyor..
evet haklısın, yaz demişim ama dur dememişim.. :2:
sonuçta c stringleri değil bunlar..
aşağıdaki gibi değiştirince düzeliyor...
strncpy( (char*) &a, (const char*) b, sizeof(A)/sizeof(char));
acehreli
27/07/2005, 19:47
nilsonmandela, "farkli seyler degil miydi" dedigin konuda const'un * isaretinin ne tarafinda olduguna bakmak gerekiyor:
const int * p; // sayi sabit
int const * p; // sayi sabit (usttekiyle ayni)
int * const p; // isaretci sabit
const int * const p; // hem sayi, hem isaretci sabit
int const * const p; // hem sayi, hem isaretci sabit (usstekiyle ayni)
Ali
acehreli
27/07/2005, 19:47
mr1yh1, bence gozardi ettigin bir konu yuzunden karisikliklar devam ediyor. Bence ortamin degistirilemeyen bir bellek bolgesi olabilecegini goz ardi ediyorsun.
Bazi bellek bolgeleri programin calismasi sirasinda gercekten degistirilemezler. (Euclides bunlari okusa, o tur bellek bolgesinin adini da verir aslinda.) O bellek icinde degisiklik yapildiginda islemci bir kesme bile atarak programin calismasini durdurabilir.
Iste, derleme zamani sabit dizgileri, dil tarafindan sabit olarak tanimlandiklari icin, bazi derleyiciler tarafindan degistirilemeyen bellek bolgelerine koyulurlar. Calisma zamaninda o bellekte a[0] = 'D' gibi bir islemle degisiklik yapmak da tanimsiz davranisa neden olur. Bu tanimsiz davranis, bazi ortamlarda programin a[0]'i D yapmasi ile, bazi ortamlarda ise programin gocmesi ile kendini gosterir.
Bu arada, biraz daha dusundukten sonra, senin aslinda bastan soyle yazmak istemis olacagini dusunmeye basladim:
char str[] = "deneme";
Bu durumda bir sorun yoktur, cunku daha onceden konustugumuz "deneme" icerikli sabit dizgiye ek olarak, bir de str adinda yerel bir dizimiz daha vardir. Simdi str[0]='D' yapabiliriz cunku str degistirelemeyen bellek bolgesinde degil, yerel nesneler bolgesindedir. (O da cogu ortamda yigittir.)
Verdigin programda "ok" diye yazdigin satir da aslinda tanimsiz davranistir. Cunku biraz once C gibi parantezli tUr donusumu isleci kullanarak bilgisayara "bana inan, o aslinda sabit degil" diyerek derleme hatasini astin. Calisma zamaninda ortamina gore yine program gocmesi yasayabilirdin.
Yine verdigin programda, degerler farkli diye sordugun yerde... C++'ta sabit degerler C'deki #define makrolari gibidirler. Derleyici onlar icin yer ayirmak zorunda bile degildir. Bir cok yerde #define makrolari kullanmanin 'const int i' yazmaktan daha iyi oldugu cunku #define durumunda i icin yer ayrilmayacagi yolundaki yanlis bilgiyi okumusumdur. Bu yanlistir; cunku C++'ta 'const int i' gibi sabitlerin de bellekte yerlerinin olmasi gerekmez.
Ancaaak, eger oyle bir nesnenin adresi alinirsa, derleyici onun icin yer ayirir. Tabii "nasil olsa sabit" diye dusundugu icin, derleyici, 'i' gecen her yerde programda tanimi verilirken atanan degeri tipki bir #define makrosu gibi kullanmasina neden olabilir.
[Bunu sckz de anlatmis.]
Sonucta, &i diye adresini aldigin icin yer ayrilmasina neden oldugun nesne ile cout << i satirinda kullandigin degerin bir ilgisi yoktur. Buradaki tanimsiz davranisin nedeni, bir nesneye sabit oldugu halde (int*) gibi bir tur donusumu ile sabit degilmis gibi davranilmasidir.
Bu son anlattigim konunun bastan konustugumuz "denemeler" dizgisi ile bir ilgisi yok tabii ki. Talihsiz bir sekilde konuyu daha da bulandirmis oldu :)
Ali
Euclides
27/07/2005, 20:41
kesinlikle acehreli'ye katılıyorum.
ve bende 1-2 şey eklemek istiyorum
#include <stdio.h>
#include <stdlib.h>
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
char* szTxt = "Super Mem";
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
int main(void)
{
szTxt[0] = 'Z';
printf("%s\n",szTxt);
return 0;
}
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
Bu kod çalışmayacaktır öyle değil mi ?
Biraz numarayla onu çalışır hale getirelim
Kodu bu şekilde derleyin
Set PATH=E:\Dev\VC\bin;E:\Dev\PSDK\Bin;%PATH%
Set INCLUDE=E:\Dev\PSDK\Include;E:\Dev\VC\include;%INC LUDE%
Set LIB=E:\Dev\PSDK\Lib;E:\Dev\VC\lib;%LIB%
Set CODS=test.cpp
Set LIBS=kernel32.lib
cl /G6 /Gz /GF /ML %cods% /link /MERGE:.data=.text /MERGE:.rdata=.text /SECTION:.text,EWR /IGNORE:4078 %LIBS%
Az önce ne yaptıkda kod çalışır hale geldi ?
exe dosyaları hafızaya kolay yüklenmeleri için kullanacakları hafızayı miktar,cins ve yer olarak belirleyen değerler içerirler.
"/MERGE:.data=.text /MERGE:.rdata=.text /SECTION:.text,EWR /IGNORE:4078"
ile 3 hafıza bölümünü(section) 1 tekinde birleştirdik ve onuda Readable,Writeable ve Executable yaptık böylece hiç read-only hafıza kalmadı ve kodmuz sorunsuz çalıştı :)
Linux için not:
ELF dosyalarıda %90 PE dosyalarına benzerler. Yukarıdaki tanım onlar içinde geçerlidir. Eğer "ld"'in manulalerine bakarsanız benzer komutları görebilirsiniz.
Eğer illaki read-only bir hafızaya yazmak istiyorum diyorsanız buda başka bir çözüm.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
char* szTxt = "Super Mem";
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
int main(void)
{
DWORD nTmp;
VirtualProtect(szTxt,strlen(szTxt)+1,PAGE_READWRIT E,&nTmp);
szTxt[0] = 'Z';
printf("%s\n",szTxt);
return 0;
}
//:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
Ancak 1 noktanın altını çizmek istiyorum kernel memory'e virtualprotect yapamazsınız.
Volkan Uzun
27/07/2005, 20:57
o kodun caluismasi icin /Gz yeterli sanirim :)
Euclides
27/07/2005, 21:12
merge bölümü çıkartarak denedim çalışmıyor :)
ayrıca cl /?'da böyle yazıyor
/Gz __stdcall calling convention
Volkan Uzun
27/07/2005, 21:13
bende calisiyor ilginc :)(
/Gz benim bildigim edit & go demek
bu sayede programi debug ederken mesela char dizisini elemanindan birini degistirirsen yeniden compile etmeden devsm edebilmeni sagliyor debugta.
bu sebeplede write able memoryde tutuyor hersdeyi.
ilginc ikimizde farkli davranmasi.
Euclides
27/07/2005, 21:19
cl /G6 /Gz /GF /ML %cods% /link %LIBS%
bununla derledim çalışmıyor...
sanırım ben Visual C++ Toolkit kullandığım için. ???
aslında stcall gerekli değil sadece benim genel derleme bat'ım bu olduğu için yaptım
/Gz'yi atarsın... çalışan ve çalışmayan örnekleri daha net şekilde elde edersin zaten önemli kısım /link'den sonrası... /G6 değil /G5 yapsan ne değişir... :)
ayrıca eklerde consol çıktısı var
Volkan Uzun
27/07/2005, 21:22
konudan iyice uzaklasiyoruz ama :) sunu denemen mumkunmu sadece /Zd ile compile etmeyi
Euclides
27/07/2005, 21:25
Evt,denedim sorunsuz çalışıyor :)
Volkan Uzun
27/07/2005, 21:26
ohh be :)
neyse Gz ile Zd karismis :)
Yine verdigin programda, degerler farkli diye sordugun yerde... C++'ta sabit degerler C'deki #define makrolari gibidirler.
Derleyici onlar icin yer ayirmak zorunda bile degildir.
Bir cok yerde #define makrolari kullanmanin 'const int i' yazmaktan daha iyi oldugu cunku #define durumunda i icin yer ayrilmayacagi yolundaki yanlis bilgiyi okumusumdur. Bu yanlistir; cunku C++'ta 'const int i' gibi sabitlerin de bellekte yerlerinin olmasi gerekmez.
Ancaaak, eger oyle bir nesnenin adresi alinirsa, derleyici onun icin yer ayirir. Tabii "nasil olsa sabit" diye dusundugu icin, derleyici, 'i' gecen her yerde programda tanimi verilirken atanan degeri tipki bir #define makrosu gibi kullanmasina neden olabilir.
...
Ali
evet işler gerçekten karıştı..
sanırım bunlar C++ deki macro kullanımını ortadan kaldırmak için uydurulmuş şeyler..
macro kullanımı ile elde edilebilecek bir etkiyi const a yüklemiş olmaları tuhaf,
sonuçta #define kullanımı çok basit ve net...
tek problem standart bir preprocessorün C++ derleyicilerinde erişilebilir olması (mesela gcc ile template lerde bir sürü problem yaşadım.. )
eskiden C++ kullanıcılarının macro kullanımına karşı allerjisinin olduğunu, ama sonradan bu yargının değiştiğini okumuştum,
şu anda da söylediğin gibi cons int kulanımı tavsiye ediliyor..
ama yukarıda gördüklerimden sonra kesinlikle sabitler için macro kullanmaya karar verdim..
bu durumda sözkonusu yapılar değişken değil literaldir....
(anlam olarak olduğu kadar, biçim (sentax) olarak da..) ve karmaşa ortadan kalkar..
mesela benim örneğimde #define kullanmış olsaydım:
#define I 12
...
// int *p = (int*) & I; //durumun sacmaligi asikar..
// *p = 13; //cunku I bir degisken degil ...
buna neden bu kadar önem verdiğime şaşırabilirsin,
ama şunu düşünüyorum :
const int j =1 ;
int add ( const int i = 1 );
senin söylediklerin ışığında ,
yukarıdaki i ve j tümüyle farklı anlamlara geliyor..
çünkü fonksiyon parametresi olarak kullandığım i , kesinlikle derleme zamanı ile alakalandırılamaz..
( macrolarda olan şey olamaz )
oysa j alakalandırılabilir..
fakat aslında biçim olarak ikiside const int ...
sanırım yukarıdaki yorum char *p = "denemeler" içinde geçerli..
const char *p = "denemeler";
int foo( const char *q = "denemeler" );
için de aynı karmaşa sözkonusu ..
q içinde derlenirken salt okunur bir bellekde yer ayırmak mümkün değil .. ( eğer euclides i doğru anlamışsam bu işin derleme zamanında yapılması lazım..)
yine bir çifte yorum gerekli..
nilsonmandela
28/07/2005, 11:17
nilsonmandela, "farkli seyler degil miydi" dedigin konuda const'un * isaretinin ne tarafinda olduguna bakmak gerekiyor:
Ali
Haklısın bir anlık bi karışıklık olmuş:)
acehreli
29/07/2005, 21:03
mr1yh1, galiba seni anliyorum. Su anda mantiksal olarak sabit (logical const) ve fiziksel olarak sabit (physical const) ayrimindan bahsetmeye basladik.
Son verdigin ornekte "denemeler" dizgisi sabittir; ve daha onceden konustugumuz gibi, derleyicisine ve ortamina gore fiziksel olarak sabit olabilir.
p ve q ise mantiksal olarak sabit dizgileri gostermektedirler. Calisma zamaninda sabit olmayan karakterleri veya fiziksel olarak sabit olan karakterleri gosterebilirler.
Dikkat edersen, p'yi de q ile ayni sinifa soktum, cunku daha sonradan gosterdigi seyi degistirmek mumkundur:
const char * p = "denemeler"; // "denemeler" fiziksel sabit olabilir
int foo(const char * q)
{
p = q; // q mantiksal olarak sabit oldugu icin
// simdi p de mantiksal olarak sabit bir dizgi gostermektedir
}
Ali
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.