kod okuma çalışmaları – 1

Bu yazıda bir kütüphanenin kod dosyasından aldığımız strrev işlevinin kodunu birlikte okuyacağız. Kod şöyle:

İşlev aldığı adresteki yazıyı ters çeviriyor ve ters çevirdiği yazının adresiyle geri dönüyor.
Ters çevirme (reverse) algoritmasını hatırlayalım: Yazının uzunluğunun yarısı kadar dönen bir döngüde yazının baştan ve sondan n. karakterlerinin takas (swap) edilmesi gerekiyor.
p1 ve p2 otomatik ömürlü char gösterici değişkenler.

C’nin güzel idiyomlarından biri. ptr bir adres olduğu için mantıksal yorumlama ptr‘nin NULL gösterici değerinde olup olmadığına bağlı olarak yapılacak.

ifadesi ile

ifadesi aynı anlamda. Eğer bu ifade doğru ise, kısa devre davranışı sayesinde mantıksal veya (logical or) işlecinin sağ terimi olan ifade hiç yapılmayacak. Eğer ptr, NULL gösterici değerinde olmasına karşın veya işlecinin sağ terimi olan ifade ele alınsaydı NULL göstericinin içeriğinin alınması nedeniyle çalışma zamanı hatası oluşurdu.

ifadesi ile

ifadesi aynı anlamda. Bu ifadenin doğru olması durumunda ptr‘nin gösterdiği yazının ilk karakterinin sonlandırıcı karakter (null character) olması demek. Bu da yazının boş olduğu yani ptr göstericisinin gösterdiği yazının uzunluğunun 0 olması anlamına geliyor. Sonuç olarak

“ptr boş olmayan bir yazıyı gösteriyorsa” şeklinde sözelleştirilebilir. Bu durumda ters çevirme işlemi yapılmamalı ya da ters çevirmeye gerek yok demek. Bu koşul doğru olduğunda işlev ptr adresi ile geri dönüyor.

döngü deyimi ile p2 göstericisi, ptr‘nin gösterdiği yazının sonunu belirleyen sonlandırıcı karakteri gösteriyor duruma getiriliyor. Döngünün gövdesinin bir boş deyim (null statement) olduğunu görüyorsunuz. Şu deyim de aynı anlama gelirdi:

Bazı kodlayıcılar da böylesi durumlarda continue deyimini kullanıyorlar:

Şimdi de döngünün kontrol ifadesine bakalım:

ifadesi ile

ifadesinin aynı anlamda olduğunu biliyoruz.
p2 göstericisinin yazının son karakterini gösterebilmesi için döngü çıkışından sonra bir kez daha eksiltilmesi gerekecek. Aynı iş, bu döngü yerine standart kütüphanenin string.h başlık dosyasında bildirilen standart strlen ya da strchr işlevleri kullanılarak da gerçekleştirilebilirdi:

ya da

Şimdi de takas işini gerçekleştiren for deyimine bakalım:

for parantezi içindeki birinci ve üçüncü ifadelerde virgül işleci kullanılmış

ifadesi ile p1 yazının başlangıç adresini p2 ise yazının son karakterini gösteriyor olacak.

ifadesi ile ise döngünün her turunda p1 gösterericisinin yazının bir sonraki karaterini, p2 göstericisinin ise yazının bir önceki karakterini göstermesi sağlanıyor.

Artık döngü gövdesinde tek yapılması gereken *p1 ve *p2 nesnelerini takas (swap) etmek. Kodlayıcı takas işlemini gerçekleştirmek için üçüncü bir değişken kullanmadan bitsel özel veya (bitwise exor) işlecinden faydalanmış. Kodlayıcımız, derleyicinin daha etkin bir kod oluşturmasını sağlamak için takas işleminin bu şekilde gerçekleştirilmesini tercih etmiş olmalı.
x ve y tamsayı değişkenler olmak üzere:

deyimi ile x ve y değişkenleri takas edilebilir. Ben bu deyimi yukarıdaki gibi yazmayı tercih ediyorum. Bu deyimi aşağıdaki gibi de yazanlar oluyor:

Yukarıdaki deyim çoğu sistemde doğru çalışsa da aslında tanımsız davranış davranış (undefined behavior) gösterdiğinden bu deyimden uzak durmalı. Bir ifade içinde yan etkiye (side effect) maruz kalmış bir nesneyi aynı ifade içinde bir yan etki noktası oluşmadan (sequence point) yeniden kullanmanın tanımsız davranış olduğunu hatırlamalıyız.
Kodlayıcımız aynı idiyomu üç ayrı deyim olarak yazmayı tercih etmiş;

Döngünün kontrol ifadesi

olduğundan ve döngünün her turunda p1 göstericisi 1 arttırıldığı ve p2 göstericisi de 1 eksiltildiği için, döngü yazının uzunluğunun yarısı kadar dönmüş olacak.
for döngü deyiminden sonra işlev ters çevrilmiş yazının adresi olan ptr değeri ile geri dönmüş:

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

kod okuma çalışmaları – 1” için 2 yorum

  1. Merhaba Hocam,

    Takas işlemini tanımsız davranışa neden olmadan aşağıdaki gibi de yazabiliyoruz sanırım.

    Bir de şöyle bir sorum var.

    char türünün işaretli mi işaretsiz mi olacağı standartlarda belirtilmemiş. Bu seçim derleyiciyi yazanlara bırakılmış. İşaretli tamsayılarda bitsel özel veya(xor) işlecinin sonucunda işaret bitinin ne olacağı tanımlı mı? Aksi halde char türünün işaretli olduğu derleyicilerde yukarıda bitsel özel veya işleci kullanarak yapılan takas işlemi tanımsız olur mu?

    Standartlarda Expressions(6.3) başlığı altında şöyle bir açıklama yapılmış. Bir noktayı yanlış anlamış olabilirim.

    Some operators(the unary operator ~. and the binary operators <<. >>. &. ^. and |. collectively described as bitwise operators) shall have operands that have integral type. These operators return value that depend on the internal representations of integers. and thus have implementation-defined aspects for signed types.

     

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Kod Eklemek İçin Okuyun