August 28, 2012

Alıntı (acehreli):

>

Şimdi C kodu üzerinde konuşuyoruz, değil mi?
Eğer bu iletime (http://ddili.org/forum/post/7503) cevap yazıyorsan orada .ptr'li örnekler verdiğim için D kodu.

Bu arada analizler için teşekkürler, tek tek deneyerek inceleyeceğim...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 28, 2012

Alıntı (erdem):

>

Bu konuda Ali bey de zaten açıklama yazmış. Ama linux altında 'cdecl' aracını da kullanabilirsin.
Teşekkürler, bundan haberim yoktu ve görünüşe göre bilgisayarımda da yokmuş! N'aptım yükledim tabi...:)
'İndirilmesi gereken dosya boyutu 26,6 kB
Bu işlemden sonra 106 kB ek disk alanı kullanılacak.
Alınıyor:1 http://es.archive.trisquel.info/trisquel/ dagda/main cdecl i386 2.5-11 [26,6 kB]
0sn'de 26,6 kB alındı (59,4 kB/s)
Önceden seçilmeyen cdecl paketi seçiliyor.'

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 28, 2012

Benim alıştıklarım da şöyle:

   int dizimiz[4][5] = /* ... */;

   int (*dizi)[5] = dizimiz;

   printf("%d", *(*(dizi + satir) + sutun));

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 28, 2012

Alıntı (Salih Dinçer):

>

Bu durumda D'de şöyle yapmalıydık:

> int * dizi = dizimiz[3].ptr;
> ```

> Peki neden 3?

dizi, dizimiz[3] diliminin ilk elemanını gösteriyor. Ondan başka bir şey değil. O göstergeyi ancak dizimiz[3]'ün elemanları üzerinde gezinmek için kullanabilirsin. Aritmetik işlemler o göstergeyi o elemanların dışında bir yeri gösterecek biçimde değiştiremezler. Yoksa C ve C++'ta da olduğu gibi, tanımsız davranıştır.

O yüzden buradaki sonuçlara bakarak bir anlam çıkartamayız.

Alıntı:
> Cevabı çok ilginç, biraz da D'deki bellek yerleşimi ve işaretçi aritmetiği ile ilgili.

Daha doğrusu, D runtime'ın bu sürümündeki çalışması ile ilgili. Hatta dilimleri uzunlukları değiştiğinde arka planda işleyen *pool allocator*'ın davranışına göre bile farklı olabilir.

Alıntı:
> Çünkü veriler belleğe ters işleniyor. Sanırım Ali hocam, D.ershane'deki bir dersde, D'de değişkenlerin aşağıdan yukarıya doğru tanımlandığını o yüzden main() dışındaki işlevlerin herhangi bir yerde (yani C'deki gibi değil!) olabileceğini yazmıştı.

Sanki yerel değişkelerin program yığıtındaki yerleşimleriyle ilgili gibia ama  kulağa hiç doğru gelmiyor. Tam yerini bulabilirsen düzeltmek isterim.

Alıntı:
> Alıntı:
> >
> >
> >
:    :    :
int (*dizi)[5] = dizimiz;
:    :    :
> >

Hocam, neden parantez kullanıyorsunuz?

Parantez olmadığı zaman "int göstergesi dizisi" olur; o dizide beş eleman varmış. Parantez olursa "beş adet int dizisinin göstergesi" olur.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 28, 2012

Şimdi C kodu üzerinde konuşuyoruz, değil mi?

   int dizimiz [4][5] = { {0, 1, 2, 3, 4},
                          {5, 6, 7, 8, 9},
                          {0, 1, 2, 3, 4},
                          {5, 6, 7, 8, 9} };

   int (* dizi) [5] = dizimiz;

// ...

       * (* (dizi + satir) + sutun)

dizimiz'in türü: Her birisi 5 int'lik 4 diziden oluşan dizi.

dizi'nin türü: 5 int'lik dizi göstergesi.

dizi+satir: dizi'nin satir kadar sonrasındaki dizi. Örneğin dizi+1 {5, 6, 7, 8, 9} dizisini gösterir.

*(dizi+satir): dizi+satir göstergesinin gösterdiği dizi. Örneğin {5, 6, 7, 8, 9} dizisinin kendisi.

*(dizi+satir)+sutun: Derleyici düşünür: Bir diziye bir tamsayı ekleniyor. Garip. Anlaşılan diziyi bir gösterge gibi kullanmak istiyorlar. O zaman şu kuralı uygulayayım: Dizinin kendisi yerine, ilk elemanı gösteren gösterge olarak davranayım. Örneğin sutun==2 olduğunda *(dizi+satir)+sutun, 7 değerli int'i gösteren bir göstergedir.

((dizi+satir)+sutun): Yukarıdaki göstergenin gösterdiği int. Yani örneğin 7 değerli eleman.

Senin son gösterdiğin kod da aynı sonucu verir ama bir farkla: Yukarıda derleyicinin garip bularak yardımcı olduğu kural sen diziyi ilklerken uygulanır:

Alıntı (Salih Dinçer):

>

Hmm anladım, peki o satırın eşdeğeri şu olabilir mi? Çünkü aynı sonucu veriyor...
Alıntı ("C KODU"):

>
> > int * dizi[4];
> >
> >       dizi[0] = dizimiz[0];
> >       dizi[1] = dizimiz[1];
> >       dizi[2] = dizimiz[2];
> >       dizi[3] = dizimiz[3];
> > ```

> >
>

dizi[0] bir int göstergesi. Ona dizimiz[0] diye bir dizi eşitlemeye çalışıyoruz. Türleri aynı değil. O zaman derleyici "diziyi ilk elemanını gösteren gösterge" olarak kullanıyor ve dizi[0]'a dizimiz[0]'ın ilk elemanının adresini atıyor. Yukarıdaki incelemeyi onun için de yapabiliriz:

dizi+satir: dizi bir dizi olduğu halde ona bir gösterge gibi davranılıyor. O zaman dizi, ilk elemanının adresi yerine geçecek. İlk elemanı bir int* olduğuna göre ilk elemanının adresi int**'dir. Örneğin dizi+1 {5, 6, 7, 8, 9} dizisinin ilk elemanını gösteren göstergedir. (Hocam bunlar çok karışık konular. :))

*(dizi+satir): dizi+satir göstergesinin göstergesinin gösterdiğidir. Yani {5, 6, 7, 8, 9} dizisinin ilk elemanı gösterilmektedir.

*(dizi+satir)+sutun: {5, 6, 7, 8, 9} dizisinin sutun'uncu elemanı gösterilmektedir.

*(*(dizi+satir)+sutun): Yukarıdaki göstergenin gösterdiği int'tir. Yani 7.

Umarım doğrudur. Bunları biraz olsun printf ile yazdırmaya çalışarak anlayabiliyoruz:


       printf("%d", dizi);


Hata mesajı bize dizi'nin türünü söylüyor:

'error: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int **’'

Ali

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
August 28, 2012

Alıntı (Salih Dinçer):

>

Alıntı (acehreli):

>

Şimdi C kodu üzerinde konuşuyoruz, değil mi?

Hayır, "C KODU" başlıklı kod için sormuştum ama zaten C demişsin. :)

Alıntı:

>

Bu arada analizler için teşekkürler, tek tek deneyerek inceleyeceğim...

Umarım doğrudur. :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 28, 2012

Evraka!

8 sayısının (sanırım) sebebini geçmişteki bir tartışmada buldum:

Alıntı (acehreli:1331839271):

>

Alıntı (Salih Dinçer):

>

Sizeof'u kullanma sebebim ise veri türünün daha büyük değişkenlerde olması durumunda

Dilimin eleman türünden bahsediyorsun o zaman. Ama veri.sizeof dediğin zaman dilim denen referans nesnesinin büyüklüğünü alıyorsun. O her zaman için bir gösterge ve bir uzunluk üyesinden oluşur. Yani her dilim 32 bitlik sistemlerde 8 bayt, 64 bitlik sistemlerde de 16 bayt olur.
Bu arada, şu aşağıda paylaştığım D denemesinden anladığım kadarıyla da dizideki veriler, belleğe kod içinde yazdığımız sırada değil tersi şeklinde yerleştiriliyor. Ayrıca her satır arasında 16 bayt fark var. Bunun 4'ü verinin kendisi olmalı çünkü her veri 32 bitlik int değeri ve zaten bunu sütunlar arasındaki farktan (4 bayt) anlıyoruz. Tabi arta kalan boşluğu (8 + 4 bayt) bakkal hesabıyla çözemediğimi itiraf etmeliyim...:)

import std.stdio;

void main(){
 int[][] dizi = [ [-1, -3, -5, -7, -9], // Negatif tek sayılar kümesinin başı
                  [ 1,  3,  5,  7,  9], // Pozitif tek sayılar kümesinin başı
                  [ 0,  2,  4,  6,  8]  // Pozitif çift sayılar kümesinin başı
                ];

 int sınır = dizi[0].length;
 int sonSatır = dizi.length - 1;
 int sonSınır = sonSatır * 8 + sınır;

 for(int adres = 0; adres < sonSınır; adres++)
 {
   if(adres < sınır)
   {
     //writef("%d\t", *(dizi[sonSatır].ptr + adres) );/*
     writef("%X\t", (dizi[sonSatır].ptr + adres) );//*/
   }
   else
   {
     adres += 2;
     sınır += 8;
     writeln;
   }
 }
 writeln;
}

Hadi, 8 bayt aradaki 'referans nesnesi'nin büyüklüğü; peki geriye kalan 4 bayt ne ola ki?

Dip Not: Belki de bu kodun aynısını C'de denemeli. Orada da benzer bir boşluk var mı? Ama şimdi çıkmalıyım...

Teşekkürler...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 29, 2012

C kodunu da denedim ve D'nin bakış açısı çok çok farklı olduğunu gördüm. Çünkü C'de alıştığımız sırada ve peş peşe veriler belleğe yerleşiyor. İşte bu yüzden tek döngü ile bir çift boyutlu diziye işaretçi aritmetiği ile erişilebilirmiş:

#include <stdio.h>

int main() {
   int dizimiz [3][5] = { {-1, -3, -5, -7, -9 }, // Negatif tek sayılar kümesinin başı
                          { 1,  3,  5,  7,  9 }, // Pozitif tek sayılar kümesinin başı
                          { 0,  2,  4,  6,  8 }  // Pozitif çift sayılar kümesinin başı
                        };
   int i;
   for(i = 0; i < sizeof(dizimiz) / sizeof(int); i++) {
       printf("%d\t", *(&dizimiz[0][0] + i));
       if((i+1) % 5 == 0) printf("\n"); // Her 5 elamandan sonra satır başı yap
   }

   return 0;
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

August 29, 2012

Ya da biraz önce konuştuğumuz gibi

   int * dizi = dizimiz[0];

Alıntı (Salih Dinçer):

>
>         printf("%d\t", *(&dizimiz[0][0] + i));
> ```

>

   printf("%2d", dizi[i]);

şeklinde de yazdırabiliyoruz :)

Bir de biraz konu dışına taşarak, C99 ile gelen ilklendirme şeklini


int dizi[6] = {[5] = 212};



iki boyutlu dizilerde kullanabiliyor muyuz acaba.

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
August 29, 2012

Evet Erdem...:)

Tam da, PicProje'ye cevap yazıyordum ki orada bu konuları bu kadar derinlemesine tartışmamızın bir kaç kişiye (belki de ikimize!) faydasının olmasından cevabı buraya yazıyorum. Çünkü biz burada PicProje kadar kalabalık olmasak da en azından tartışmadan faydalanan kişi sayısı ikinin üzerinde...

Yine de D'ye nefer (Dici...:)) yetiştirmek için sık sık forumlara birlikte dalalım mı? Aslında yetiştirmek yanlış kelime. İnsanların ilgisini çekmek için yapmamız gereken bir yayılma politikası olabilir. Çünkü ceviz kabuğu gibi içimize çekilmenin manası yok. "ceviz" demişken (başka başlıkta tartışmak üzere...) Ceviz Forum'da D kategorisi n'oldu? Bu konuda foruma dair istekler kısmında bir başlık (http://forum.ceviz.net/ceviznet-hakkinda/120355-d-dili-kategorisi.html) açmıştım. Sanırım hiç ilgilenen olmadı...:(

Konuyu Ali hocama havale ediyorum...:)

Alıntı (acehreli):

>

C'de dizi diye ayrıca bir tür olmadığı için öyle oluyor. D'de C dizilerine en yakın olan şey statik dizilerdir (uzunluğu derleme zamanında bilinen).

Burada bir şey daha anlıyoruz: D'de dizi içine dizi yerleştirdiğimizi sanıyoruz ama aslında içtekiler dilim. Dilimlerin de dizi kavramıyla tek yakınlıkları, D çalışma ortamının (D runtime) bizim için yönettiği elemanlara erişim sağlamak.

Salih, gördüğün 16 bayt herhalde hizalama (alignment) ile ilgilidir. Şurada "Türlerin .alignof niteliği" başlığında var:

http://ddili.org/ders/d/bellek_yonetimi.html

Belki 64 veya 32 bit derleme arasında fark görebilirsin.

Şimdi biraz daha düşündüm: Benim sistemimde 16 bayt tutmasının nedeni, dilimlerin iki üyesinin de 8 bayt olmasından geliyor: size_t türünde uzunluk ve eleman göstergesi.

Evet, bu konuları ben de sakin bir zamanım da etraflıca düşünmek istiyorum. Çünkü D'yi daha iyi anlayabilmek için (arta alanda ne haltar çevirdiğini bilebilmek) az da olsa işaretçilere girmek gerekiyor. Erdem sayesinde bu gerçekleşti ve hayatımda hiç bu kadar işaretçilere yakınlaştığımı hatırlamıyorum...:)

Peki ya C++ standartları desek...

Örneğin şu an elimde bir CPP project var ve ben o gelenekten yetişmediğim için bazı yapıları anlayamıyorum! Özellikle aşağıdaki kod; yıldız yerinez adres işaretinin sola bitişik yazılmış. Ayrıca dönüş değeri belli olmayan (zannedersem void?) işlevler görüyorum. Bu aşağıdaki sadece biri...:(

struct Settings : public MethodConfig
{
	AsrJuristicsMethod asr_juristics_method;		 // Juristic method for Asr
	double asr;		                              // Asr minutes if method is minutes
	HighLatitudeMethod high_latitudes_method;		// adjusting method for higher latitudes

	Settings& operator=(const MethodConfig& method_config)
	{
		reinterpret_cast<MethodConfig&>(*this) = method_config;
		return *this;
	}
};

Bu CPP kodunun D karşılığı olabilir mi? Bana yardımcı olacaklardan Allah razı olsun...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]