Tam Sürümünü Görmek İçin : Diziler
quasimodo
06/03/2007, 16:12
Simdi diziler hakkinda birkac birsey soracagim...
ve soracaklarim C adina ......
int n = 10;
int array[n];
Bu kodun yanlis olmasinin nedeni dizilerin derleme
zamaninda boyutlarinin belirli ve sabit olmasi gereklidir
ama n degiskeninin degeri run time de 10 olmasindandir...
O zaman bu mantikla ben neden :
int static n = 10;
int array[n];
boyle bir sey yapamiyorum. n degiskeni static tanimlandigi
icin derleme zamaninda degeri 10 olmuyormu ?
necipakif
06/03/2007, 19:37
quasimodo, #define ön tanımlayıcısını kullanırsan sorununu çözmüş olursun. Ya da static ile const değişken tanımlama hakkında bilgi toplarsan da sonuca gene ulaşmış olacaksın.
Örnek tanımlamalar:
#define SIZE 3
int main()
{
int array[SIZE];
.....
}
ya da
int main()
{
const int SIZE = 3;
int array[SIZE];
..........
}
Selametle...
quasimodo
06/03/2007, 21:32
const int n;
in dizi[n];
kodu ANSI C de gecerli bir kullanim degildir.
Basinda yazdigim gibi C adina konusuyorum.
Aslinda benim ogrenmek istediklerim daha farkli seylerdi...
int n;
yaptigimda n degiskeni icin bellekte yer ayirma yada
daha dogrusu uygun bir yer bulma islemi
ne zaman yapiliyor?
Euclides
06/03/2007, 21:54
yaptigimda n degiskeni icin bellekte yer ayirma yada
daha dogrusu uygun bir yer bulma islemi
ne zaman yapiliyor?
malesef bunun için bir standart yok, hatta hiç bellek ayırmayıp onun yerine bir register'de kullanabilir. Fakat vc++ ile tüm optimizasyonları kapatırsan
eğer n bir local değişkense fonksiyonun girişinde tüm local değişkenlerin büyüklüğü kadar bir parça stack register(esp)'den çıkartılır. Global bir değişkense n'in büyüklüğü kadar .data section'una 0x00 eklenir.
acehreli
06/03/2007, 22:10
quasimodo, gecerli olmadigini soyledigin kod sen n'e ilk deger vermedigin icin oyle. Cunku sabitlerin ilk degerlerinin bildirildikleri noktada verilmeleri gerekir. Sonradan deger atayamayiz ya...
Yoksa
const int n = 3;
int dizi[n]; // dogru
kullaniminda bir yanlislik yok. Cunku orada dizi buyuklugu olarak bir "constant expression" (sabit ifade) kullaniliyor.
Ali
quasimodo
06/03/2007, 22:16
Sevgili Euclides cevap icin tesekur ediyorum
ama benim sorum nerede degil nezaman olduguydu?
yani locak degiskenler yani otomatik degiskenler
stack segment te global degiskenler data segment te
saklandigi konusunda bilgim var....
En iyisi ben bildigimi anlatiyim yanlissa duzeltirsiniz...
int birSayi;
gibi bir ifade de derleyici derleme zamaninda bellekte
uygun bir adresi bulur ve birSayi nin adresi artık o
adrestir ve icinde garbage deger vardir.
birSayi = 10;
ifadesi ise run timede isleme sokulur. Yani degiskenin degeri
calisma zamaninda degisir.
Ozetle;
Bildirim islemi derleme zamaninda deger verme yada garbage degeri
degistirme islemi calisma zamaninda yapilir. Bildiklerim dogrumu?
Ali Hocam ilk deger vermeyi unutmusum ama verili olsaydida
bu tanimlama C de gecerli degil ama C++ ta gecerli ....
Euclides
06/03/2007, 23:07
Sevgili Euclides cevap icin tesekur ediyorum
ama benim sorum nerede degil nezaman olduguydu?
Zamanı yeri ile ilgili, stack'dan ayırma işlemi fonkisyonun ilk komutu olarak işletiliyor bir başka değişle runtime'da yapılıyor
int birSayi;
gibi bir ifade de derleyici derleme zamaninda bellekte
uygun bir adresi bulur ve birSayi nin adresi artık o
adrestir ve icinde garbage deger vardir.
Eğer global ise (ve vc + hiçbir optimizazyon yoksa) böyle ancak local ise runtime'da ayırılmış olur
birSayi = 10;
ifadesi ise run timede isleme sokulur. Yani degiskenin degeri
calisma zamaninda degisir.
[/CODE]
Eğer optimizazyon yoksa böyle olacaktır.(tabii birSayi'nın constant olmadığı var sayımını yapıyoruz)
Sizin için ayrı bir kod yazıp onun üzerinde göstermek isterdim ancak biraz yorgumun o yüzden elimdeki bir kodu kullanacağım
eklerdeki resimlerde C<->asm gecişini görebilirsiniz. Asm bilmeniz gerekli değil kodlardaki benzerliğe dikkat edin. Asm kodu olarak gördüğünüz herşey runtime'da meydana geliyor demektir.
Sevgili quasimodo bir çok şeyi birbirine karıştırmışsın. PE dosya formatını anlamadan bunları anlamak çok zor.
Sevgili Euclides cevap icin tesekur ediyorum
ama benim sorum nerede degil nezaman olduguydu?
yani locak degiskenler yani otomatik degiskenler
stack segment te global degiskenler data segment te
saklandigi konusunda bilgim var....
En iyisi ben bildigimi anlatiyim yanlissa duzeltirsiniz...
int birSayi;
gibi bir ifade de derleyici derleme zamaninda bellekte
uygun bir adresi bulur
Derleme anının bellek ile alakası yoktur. Büyük ihtimalle derleme derken örneğin VC++ 'ta bir kodun derleme+bağlama+ işletim sistemi tarafından yükleme işlemlerinin toplamından bahsediyorsun ki her bi aşama çok ayrıntılı.
Derleme+Linking (bağlama) aşamasında memory ile işimiz yok. Dolayısyla ortada ne stack segment ne de data segment var. Dolayısıyla yukarda yazdıkların yani bunlar:
"locak degiskenler yani otomatik degiskenler stack segment te global degiskenler data segment te saklandigi konusunda bilgim var" anlamsız.
ve birSayi nin adresi artık o
adrestir ve icinde garbage deger vardir.
Hayır yanlış böyle birşey yok. Daha doğrusu anlamsız bu kurulan varsayım.
birSayi = 10;
ifadesi ise run timede isleme sokulur. Yani degiskenin degeri
calisma zamaninda degisir.
Herşey runtimeda işleme sokulur. Runtimeda Loader işini düzgün yapsın diye bir ton bilgi vardır PE'nin içinde. Ama bu dediğin gibi önce garbage değer sonra başka değer diye birşey yok.
Ozetle;
Bildirim islemi derleme zamaninda deger verme yada garbage degeri
degistirme islemi calisma zamaninda yapilir. Bildiklerim dogrumu?
İnan bunların çoğu efsane. Tekrar toparlarsak compiling yani derleme aşamsında .obj dosyası çıkar ve burda segment değil sectionlar vardır. Her .c dosyası için bir .obj dosyası vardır. Ve içinde tüm değerler yazılıdır ( bellekte değil şu anda harddikteyiz). Daha sonra .obj ve diğer gerekli dosyalar linker(bağlayıcı) ya girer ve tek bir exe oluşturur.(hala daha harddikteyiz).
Artık exeyi istediğmiz zaman çağırırız. Cağırdığımız anda kullandığımız sistemin loaderi devreye girip PE dosyayı memory kendine has hizalamalarını ve .reloc tablosunu kullanarak yükler. İşte şimdi bellekteyiz ve segmentler yeni oluşturuldu.
Yani bu iş biraz karışık. Sorduğun soru ve anlattıkların ise açıkçası anlamsız. Yada ben anlamadım ne demek istediğini.
Compiling+Linking+Loading üçü de ayrı safhadır. Üçünü de ayrı ayrı okumak lazım.
Bunun için sana şu kitabı tavsiye ederim:
Linkers and Loaders
http://www.iecc.com/linker/
Görüşmek üzere...
acehreli
07/03/2007, 00:54
Euclides'in gosterdigi gibi, yerel degiskenlerin yeri derleme zamaninda ayrilmaz. Derleme zamaninda olan sey, kod olusturmaktir; o yerel degiskenlerin yerini ayiracak kodu olusturmaktir.
Yoksa ozyinelemeli islevler calismazdi degil mi... Derleyici yerel degiskenlerden kac tane ayiracagini derleme zamaninda bilemezdi.
void foo(int sayi, int son_deger)
{
int yerel = son_deger - sayi;
if (yerel == 0) return;
foo(sayi + 1, son_deger);
}
Derleyici yerel degiskenin yerini derleme zamaninda ayiramaz cunku islevin kac kere yenilenecegini bilmiyor.
Ali
quasimodo
07/03/2007, 18:01
İnan bunların çoğu efsane. Tekrar toparlarsak compiling yani derleme aşamsında .obj dosyası çıkar ve burda segment değil sectionlar vardır. Her .c dosyası için bir .obj dosyası vardır. Ve içinde tüm değerler yazılıdır ( bellekte değil şu anda harddikteyiz). Daha sonra .obj ve diğer gerekli dosyalar linker(bağlayıcı) ya girer ve tek bir exe oluşturur.(hala daha harddikteyiz).
Artık exeyi istediğmiz zaman çağırırız. Cağırdığımız anda kullandığımız sistemin loaderi devreye girip PE dosyayı memory kendine has hizalamalarını ve .reloc tablosunu kullanarak yükler. İşte şimdi bellekteyiz ve segmentler yeni oluşturuldu.
Peki static nesnelerde durum nasil?
Derleyici bir static nesneyle karsilastiginda uygun kodu olusturur. Bu olusturulan kodda adres belli degil (yukaridaki alintidan cikardigim sonuc daha segmentler olusmamis ), ama uygun adres bulundugunda (run time da) icine konulacak deger bellidir. ( sifir yada verdigim baska bir ilk deger ). Dogrumuyum ???
Yani derleme aninda hicbir degiskenin dinamik yada static adresi belli degildir ama icine konulacak deger staticse belli dinamikse belli olabilirdir(ilk deger verip vermemeye gore)???
Euclides
07/03/2007, 20:17
Yani derleme aninda hicbir degiskenin dinamik yada static adresi belli degildir ama icine konulacak deger staticse belli dinamikse belli olabilirdir(ilk deger verip vermemeye gore)???
Biran için bunun doğru olduğunu düşünelim, hiçbir global değişkene erişemezdik çünkü nerde olduklarını bilemezdik...(local'lere erişirdik çünkü onların adresleri esp'in değerine göre izafidir.(mesela "esp+12" gibi...))
segment'lerin belirsiz olması offsetlerinde belirsiz olduğu anlamına gelmez. Hatta çalışan bütün processlerin tüm segement değerinin "görsel kısmı" aynıdır. (Intel'in manuellerinde "visual part" olarak geçiyor)
Peki static nesnelerde durum nasil?
Derleyici bir static nesneyle karsilastiginda uygun kodu olusturur. Bu olusturulan kodda adres belli degil (yukaridaki alintidan cikardigim sonuc daha segmentler olusmamis ), ama uygun adres bulundugunda (run time da) icine konulacak deger bellidir. ( sifir yada verdigim baska bir ilk deger ). Dogrumuyum ???
Yani derleme aninda hicbir degiskenin dinamik yada static adresi belli degildir ama icine konulacak deger staticse belli dinamikse belli olabilirdir(ilk deger verip vermemeye gore)???
Selamlar arkadaşlar
quasimodo bir önceki cevabım yalnızca son sorduğun soruya yönelikti. İlk sorunu ele alacak olursak yani
static int n = 10;
int dizi[n]
bunun neden derlem zamanında hata verdiği ile ilgili olanı. Cevabında karşıma ilginç bir bilgi çıktı. Bunun cevabını burda alabilirsin:
http://blog.kalmbachnet.de/?postid=33
Normalde static değişkenler PE dosyanın içinde .bss'de tutulurlar. .bss'de ise oluşturulmamaış değerler tutulur ama adres olarak düşünme. Sen işin içine adresi de kattığından problem çok daha farklı hal aldı beni de yanılttın biraz.
.bss'deki değişkenler için prosedurde 0'a eşitlenme olayı var. uninitialize section ve 0'a eşitleme ile ilgili ilginç bir durum varmış. Onu da bu verdiğim linkten okuyarak görebilirsin.
http://blog.kalmbachnet.de/?postid=33
Görüşmek üzere...
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.