Baştan not: Yazdıklarımı tekrar okuduğumda ses tonumun biraz sinirli olduğunu görüyorum. (Aslında gerçekten sinirliyim de. :-p) Ama bunları kimseye karşı değil, C'nin tutarsız söz dizimini çekinmeden söyleyerek yazıyorum.
Öncelikle bu dillerin hiçbirisinde çok boyutlu dizi olmadığını hatırlayalım. Dizi dizisi oluşturunca bizim çok boyutlu dizi dediğimiz yapı oluşuyor. Ama dillerde özellikle çok boyutlu dizi diye bir olanak yok.
Bu durumda, bu boyutlardan hangisinin satır hangisinin sütun olduğu da tamamen programın tasarımına kalıyor. Programcı tutarlı olarak birinci indisi örneğin satır olarak kullanıyorsa sorun yok.
Şimdi C ve D dillerindeki dizi tanımlarına bakalım. (C++'ta da C ile aynıdır ama C++'ta zaten std::vector topluluğu olduğu için dizi kullanılmaz, veya kullanılmamalıdır.)
C'nin söz dizimi şöyledir:
Tür isim[adet];
Yani örneğin 3 adet char'dan oluşan bir dizi oluşturmak istesek:
char d[3];
Buraya kadar güzel. Şimdi, her elemanı 3 char'lık dizi olan bir dizi oluşturmaya çalışalım. Yani öyle bir dizi olacak ki, 'd[0]' dediğimizde eriştiğimiz elemanın kendisi 3 char'lık dizi olacak.
C'de şu saçma söz dizimi ile tanımlanır:
char d[2][3];
Hani adet sağ tarafa geliyordu! Hmmm? :-p Demek ki değilmiş. Aslında tek boyutlu dizi oluşturduğumuzda da adedi sağa değil, görünmez bir karakterle ismin arasına mı yazmışız acaba? Herhalde... mi acaba? :-p Yani aslında adet, araya bir yere giriyormuş. Saçma.
Yukarıdaki tanımın gerçekten de her elemanı 3 char'lık dizi olan 2 elemanlı dizi tanımladığını 'd[0]''ın büyüklüğünü yazdırarak görebiliriz:
#include <stdio.h>
int main()
{
char d[2][3];
printf("%zu\n", sizeof(d[0]));
}
O programın çıktısı 3'tür. Yani buraya kadar söylediklerim doğru.
İşin garibi, kod typedef ile kolaylaştırılınca her şey mantıklı olmaya başlar:
#include <stdio.h>
typedef char ElemanTuru[3];
int main()
{
ElemanTuru d[2];
printf("%zu\n", sizeof(d[0]));
}
İçteki dizinin adedini 'ElemanTuru' kendi içinde gizli olarak taşımaktadır. Tabii böyle bakınca, bu sefer '[2]' araya değil, gerçekten de sağa gelmiş oluyor.
(Ayrıca typedef tanımında ElemanTuru'nün de nasıl yine araya yazıldığına dikkat edin. O tanım aynı derecede saçma bir konudur... Daha da büyük saçmalık işlev göstergelerinde ortaya çıkar ve işlev göstergesi döndüren işlev göstergesi durumlarında beyni eritir! :-p)
C'nin böyle olmasının nedeni herhalde eleman erişimindeki adetlerle dizi tanımı sırasındaki indekslerin denk konumda bulunmalarıdır:
a = d[x][y];
O kullanım, 2 elemanlı dizinin x'inci elemanının 3 elemanından y'incisine erişmektedir.
Bütün bunlara alışmış olan ve sorgulamadan kullanan C programcılarına göre D'nin tutarlı tanımı terstir.
D'de dizi söz dizimi şöyledir:
Tür[adet] isim;
Bu diğer değişkenlerin tanımı ile de tutarlıdır: önce tür, sonra isim. Basit...
Şimdi her bir elemanı 3 char'dan oluşan 2 elemanlı bir dizi tanımlayalım. Her bir eleman 'char[3]' olduğuna göre onu Tür'ün yerine yazacağız ve bu dizide 2 adet eleman olduğu için de adet yerine 2 yazacağız. Kolay ve tutarlı:
char[3][2] d;
Bunun doğru olduğunu görmek için yine bu dizinin ilk elemanının büyüklüğünü yazdıralım:
import std.stdio;
void main()
{
char[3][2] d;
writeln(d[0].sizeof);
}
Onun çıktısı da 3 yazar.
Şimdi C programcılarının D'nin eleman erişimini ters bulmalarını anlamaya çalışalım. Aslında hiçbir terslik yoktur. '[]' işlecinin yaptığı, solundaki değişkenin belirli sıra numarasındaki elemanına eriştirmektir. Bunu zaten yukarıda kullandık: 'd[0]' yazdığımız zaman d'nin ilk elemanına eriştik. Şimdi o 3 char'dan oluşan elemanın son char'ını 'a' yapalım:
d[0][2] = 'a'; // ilk elemanın son char'ı
writeln(d);
Çıktısında görüldüğü gibi, birinci elemanın 2 numaralı char'ı 'a'nın değeri olan 0x61 olmuştur:
'[x"FF FF 61"c, x"FF FF FF"c]'
Aslında burası C'de de aynıdır. O yüzden C programcıları olsa olsa D'deki dizi tanımını ters bulabilirler; eleman erişimini değil... Ama bunu da ben anlayamıyorum, çünkü D tutarlı, C ise saçma.
Not 1: char'ın ilk değerinin geçersiz bir karakteri gösteren 0xff olduğunu da görüyouruz.
Not 2: char dizilerinin o biçimde yazdırıldıklarını bilmiyordum. Şöyle de seçebilirlerdi ama herhalde zaman fazla kalabalık oluyor diye yapmamışlar: '[ [ '\xFF', '\xFF', '\x61' ], [ '\xFF', '\xFF', '\xFF' ] ]'
Not 3: Dizgi hazır değerlerinin 'x"..."' düzeninde de yazılabildiklerini şu bölümde "Onaltılı sistemde yazılan dizgiler" başlığında görmüştük: http://ddili.org/ders/d/hazir_degerler.html
Sonuçta hem tanımda hem de erişimde D tutarlıdır. C ise tanım sırasında adet bilgisini araya sokuşturduğu için garip, ve adedi ismin sağ tarafına attığı için diğer değişken tanımlarıyla tutarsızdır.
Alıntı (zafer):
> Neticede tanıma bakarak D_gibi[0] indeksinin 1, 3, 5 sayılarını getirmesi gerekiyor gibi görünüyor
'[1, 3, 5]' beklemenin nedeni benim satır ve sütun demem nedeniyle olmuş herhalde.
Tekrarlarsam, C'de ve D'de bütün diziler tek boyutludur. Dizi dizisini istediğimiz anlamda kullanmak bize kalmıştır. D_gibi'nin tanımına bakınca ben şunu görüyorum: her birisi 2 sütundan oluşan 3 satır... O yüzden 'D_gibi[0]' yazınca birinci satırı elde ediyoruz ve onun iki sütunu var.
Alıntı (zafer):
> Buradaki köşeli parantezler program çıktısına otomatik mi ekleniyor?
Evet, her değişken kendi türüne uygun olarak yazdırılıyor ve writeln ve arkadaşları dizileri o biçimde yazdırıyorlar. Programımıza uymadığı durumlarda kendimiz sırayla da yazdırabiliriz tabii. (Yazdırılırken çıkış olarak bir dizgi de kullanılabilmesi de düşünülüyor ve onun tartışmaları da az hararetle devam ediyor.)
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]