Dizi indisleri 0'la mı yoksa 1'le mi başlamalı? Bana öyle geliyor ki, 0.5 olması konusundaki önerim yeterince düşünülmeden reddedildi.

Stan Kelly-Bootle

Bana Atılan E-Postaların Yanıtları

Sevgili Arkadaşlar...

Bu site aracılığıyla -bazıları sorulardan oluşan- pek çok e-posta alıyorum. Ancak yoğunluk nedeniyle bazılarına yanıt yazamadım.  Sakın unuttum sanmayın ve "adam bir yanıt bile yazmadı" diye düşünmeyin :-). Bundan sonra atacağınız e-postalara da daha kısa bir süre içinde yanıt vermeye çalışacağım. Gecikme için özür diliyorum...

 

Lütfen Alıntılarda Kaynak Belirtiniz

Çeşitli Internet sitelerinde yazmış olduğum makalelerden, ders notlarından, çizimlerden, kaynak kodlardan vs. bire bir alıntı yapıldığını, ancak kaynak belirtlmediğini görüyorum. Lütfen bu gibi alıntlarda kaynak belirtiniz.

Kitap Eleştirisi

Artık her hafta sitede bilgisayar alanında basılmış bir kitabın eleştirisini göreceksiniz. Umarım beğenirsiniz...

Tarihe Göre

Yeni İçerik

C’nin Standart Dosya Fonksiyonlarının Uyguladığı Tamponlama Mekanizması

    Standart C fonksiyonlarını kullanmadan bir dosyanın her byte’ı üzerinde sırasıyla işlem yapmak isteyelim. Herhalde ilk akla gelecek yöntem doğrudan işletim sisteminin sistem fonksiyonlarını çağırmak olacaktır. Örneğin UNIX/Linux sistemlerinde dosyayı read fonksiyonuyla (Windows sistemlerinde ReadFile fonksiyonuyla) byte byte aşağıdaki gibi okuyabiliriz:
 
int fd;
ssize_t result;
unsigned char ch;

if ((fd = open("test", O_RDONLY)) < 0) {
    perror("open");
    exit(EXIT_FAILURE);
}

while ((result = read(fd, &ch, 1)) > 0) {
    /* Okunan byte işleniyor */
}   

if (result < 0) {
    perror("read");
    exit(EXIT_FAILURE);
}   

close(fd);

Programların Komut Satırı Argümanları

    İşletim sistemi tarafından prosese geçirilen komut satırı argümanları program içerisinden çeşitli biçimlerde elde edilebilmektedir. En yaygın yöntem komut satırı argümanlarının programın başlangıç fonksiyonunun parametrelerinden elde edilmesidir. Örneğin, C ve C++’ta komut satırı argümanları main fonksiyonuna parametre olarak geçirilirler. Bu dillerin standartlarına göre programın başlangıç noktasını (entry point) belirten main fonksiyonunun parametrik yapısı ve geri dönüş değeri aşağıdaki iki durumdan biri biçiminde olmalıdır:

int main(void)  { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }

UNIX/Linux Sistemlerinde Proseslerin Yaratılması ve Sonlandırılması

    Hemen her işletim sistemi bir proses yaratıldığında o prosese özgü bilgileri bir veri yapısında saklar. Çalışmakta olan proseslere ilişkin bilgilerin saklandığı veri yapısına proses kontrol bloğu denilmektedir.[1] UNIX türevi sistemlerde prosesin gerçek ve etkin (effective), kullanıcı ve grup id’leri, prosesin çalışma dizini, açmış olduğu dosyalar gibi prosese özgü önemli bilgilerin hepsi proses kontrol bloğunda tutulmaktadır. Proses kontrol bloğunun nasıl düzenlendiği ve tam olarak hangi elemanlara sahip olduğu sistemden sisteme, hatta aynı sistemlerde versiyondan versiyona değişebilmektedir. Örneğin Linux sistemlerinde proses kontrol bloğu oldukça fazla elemana sahip olan task_struct yapısı ile temsil edilmiştir.  Bu yapının bir bölümünü aşağıda veriyoruz (Version:2.6.35, include/linux/sched.h):

UNIX/Linux ve Windows Sistemlerinde Stdin, Stdout ve Stderr Dosyaları

    Yalnızca UNIX/Linux sistemlerinde değil modern işletim sistemlerinin çoğunda aygıtlar birer dosyaymış gibi ele alınmaktadır. Örneğin klavye ve ekran -aslında birer dosya olmadığı halde- işletim sistemi tarafından sanki birer dosyaymış gibi işleme sokulurlar. Aygıtlara ilişkin bu tür dosyalar için de birer dosya betimleyicisi ve dosya nesnesi vardır. Bu betimleyicilerle işlem yapıldığında işletim sisteminin dosya alt sistemi aslında bu dosyaların birer aygıta ilişkin olduğunu anlar ve okuma/yazma amacıyla o aygıtlara yönelir. UNIX türevi sistemlerdeki çokbiçimliliği (polymophism) andıran bu tasarıma Sanal Dosya Sistemi (Virtual File System) denilmektedir.  

C#'taki Yapı ve Sınıf Nesneleri Nerede Yaratılıyor?

Pek çok C# programcısının sınıf ve yapı kavramlarıyla stack ve heap kavramlarını yanlış bir biçimde ilişkilendirdiğini görüyorum. Örneğin, “yapı nesneleri stack’te sınıf nesneleri heap’te tutulur” biçiminde yanlış anlaşılmaya yol açacak bilgiler veren yerli ve yabancı çok sayıda yazı ve makaleyle karşılaştım. Konuya biraz açıklık getirmek istiyorum.

UNIX/Linux Sistemlerinde Dosya Betimleyicilerinin Anlamı

    UNIX/Linux sistemlerinde her prosesin proses tablosu yoluyla erişilen bir dosya betimleyici tablosu (file descriptor table) vardır. Dosya betimleyici tablosu bir gösterici dizisi biçimindedir. Betimleyci tablo içersindeki her gösterici açılmış bir dosyanın bilgilerinin tutulduğu ve ismine dosya nesnesi (file object) denilen bir veri yapısını gösterir. open fonksiyonundan elde edilen dosya betimleyicisi (file descriptor) prosesin dosya betimleyici tablosunda bir indeks belirtmektedir.

Proseslerin Çevre Değişkenleri

    Modern işletim sistemlerinde her prosesin bir çevre değişken bloğu vardır. Prosesin çevre değişken bloğu çevre değişkenlerinden ve onların değerlerinden oluşmaktadır. Örneğin, MESAJ bir çevre değişkeninin ismi olabilir, “Merhaba Dunya” ise onun değeri olabilir. Çevre değişkenleri pek çok işletim sisteminde proses yaratılırken belirlenebilmekte  ya da üst prosesten (parent process) aktarılabilmektedir. Çevre değişkenlerinin üst prosesten aktarılması en çok karşılaşılan tipik durumdur.

Mayıs
26
2009

Programlama Dillerindeki Kuralların Gerekçeleri

    Doğal dillerdeki kurallar matematiksel anlamda kesin değildir, bunların istisnaları çoktur. Zaten bizi herhangi bir şey öğrenirken bezdiren şeylerden biridir istisnalar. Örneğin İngilizce’de daha yüksek demek için high sıfatı higher haline, tall sıfatı taller haline geliyor. Pek çok sıfatın bu biçimde "er" eki aldığını görüyoruz. Fakat bu kesin bir kural mı? Hayır, bunun pek çok istisnası var. Örneğin, (her nedense) kötü bad olduğu halde daha kötü için worse kullanılıyor. (Ana dil gibisi var mı? Hepimiz kırmızı için kıpkırmızı, mavi için masmavi denildiğini biliriz. Bunun bir kuralının olup olmadığını sorgulamamışızdır. Zaten umurumuzda da değildir. Kimse kırmızı için maskırmızı demez.)

    Fakat programlama dillerinin kesin kuralları ve bu kuralların da çeşitli gerekçeleri vardır. (Örneğin “case ifadeleri sabit ifadesi olmak zorundadır” kuralının gerekçeleri vardır ve ben bunu geçen haftalarda açıklamıştım.) Çünkü programlama dilleri doğal diller gibi uzun bir süre içerisinde toplumsal bir yaşantıyla ortaya çıkmıyor. Bunlar mantık temelinde bilinçli olarak tasarlanıyorlar. Herşeyden önemlisi programlama dillerinin sentaks yapıları matematiksel olarak açıklanabiliyor. Bu nedenle bu tür dillere biçimsel diller (formal languages) denilmekte. 

    Programlama dillerindeki bazı kuralların bazı gerekçeleri o dili kullanan herkes tarafından tahmin edilebilir. Fakat bazı gerekçelerin anlaşılması ve kavranması yüksek bir bilinç düzeyini gerektirir. Neden mi? Çünkü bazı kuralların gerekçelerini anlayabilmek için başka şeylerin bilinmesi gerekir de ondan. Örneğin, pek çok programlama dilinde goto ile başka bir fonksiyona atlama yapılamaz.  Bu kuralın gerekçesini stack mekanizmasını bilmeyen bir kişiye nasıl açıklayabiliriz? 
    
    Bazı programlama dillerinde kuralların gerekçeleri resmi dökümanlar halinde açıklanmaktadır. Örneğin C90 ve C99 için özel hazırlanmış gerekçeler (rationale) eki resmi bir açıklama niteliğindedir. Bazı programlama dillerinde ise bazı gerekçelerin standartların kendi içerisinde doğrudan açıklandığını görürüz. Örneğin, C#’ta bazı kuralların gerekçeleri bu biçimde standartların içerisinde belirtilmiş durumda. Peki genel olarak bir kuralın gerekçesini nasıl öğrenebiliriz? Öncelikle eğer varsa resmi dökümanlara bakmanızı tavsiye ederim. Eğer böyle bir döküman yoksa  bu durumda tasarımcıların hazırladıkları kitaplar, makaleler ya da onlarla yapılan röportajlar ve söyleşiler iyi bir kaynak olabilirler. Örneğin, Stroustrup’un “The Annotated C++ Reference Manual” isimli kitabı -eski olmasına karşın- C++ için iyi bir gerekçe açıklama dökümanı olarak kullanılabilir. Ya da örneğin C++/CLI için “A Design Rationale for C++/CLI” makalesini kullanabilirsiniz. USENET haber grupları, tartışma grupları, blog’lar yine kaynak oluşturabilirler. Zaten görüyorsunuz, ben de kendi blog’umda arada sırada bazı gerekçeleri açıklamaya çalışıyorum. 

    Peki ya tasarımcılar tarafından oluşturulan kurallar ve bunların gerekçeleri her zaman bizi ikna edebiliyor mu? Yanıt hayır! Bu bağlamda ben pek çok dildeki pek çok kuralı gerekçeleriyle birlikte eleştiriyorum. Örneğin, C#'taki switch deyiminde aşağıya düşme kuralının (fall through) kaldırılarak bunun dolaylı bir biçimde goto case ve goto default deyimleriyle karşılanmasını gereksiz ve saçma buluyorum. Bu konuda Hejlsberg'in belirttiği gerekçeler de beni tatmin etmiyor. Tabi gerekçeleri gözden geçirirken o programlama dilinin seviyesini, kullanım alanını ve programlama modelini göz önüne almak zorunda olduğumuzun farkındayım. Fakat siz de bazen "neden şöyle değil de böyle" diye merak ettiğiniz kuralların pekala "şöyle" de olabileceğini gözardı etmeyin. Çünkü bazı durumlarda tasarımcının elinde birbirine yakın birden fazla seçenek vardır. Bu seçenekler neredeyse eşdeğer işlevselliktedir. Tasarımcı da bunlardan birini seçmiştir.

    Programlama dillerindeki bazı kurallar da zamanla değiştirilebiliyor. Buna tipik bir örnek olarak C++’taki deyimlerin parantezleri içerisinde bildirilen değişkenlerin faaliyet alanı verilebilir:

for (int i = 0; i < 100; ++i) {
    //...
}

i değişkeni nerede bildirilmiştir? Stroustrup önce bunun for döngüsünün yerleştirildiği blokta bildirilmiş olması gerektiğini düşünmüştür. Fakat bu kural yeterince işlevsel değildir. Yukarıdaki döngüyü biraz aşağıya kopyalarsanız hata oluşur. Bu kural daha sonra (standartlarla birlikte) değiştirilmiştir. Bugün artık C/C++ kökeninden gelen pek çok dilde bu değişkenlerin faaliyet alanları döngü bloğu ile sınırlıdır.

    Programlama dillerinin tasarımında ve standartlarında böcek olmuyor mu? Tabi oluyor. Fakat bunları zamanla düzeltiyorlar. Bugün Internet sayesinde çeşitli ortamlarda pek çok yeni fikir tartışılabiliyor ve eski fikirler eleştirilebiliyor. Tabi geçmişe doğru uyumun bozulması bazen tüm çabalara rağmen engellenemiyor...

Haftanın Böceği Yukarı