Gömülü C – 7 : Fonksiyonlar ve Temiz Kodlama

İngilizce’de “clean coding” (temiz kodlama) denilen mevzu ile ilgi, cüz-i irademden dökülen bir takım fikir ve ilmi bilgileri,  siz değerli okurlarla paylaşacağım.

Temiz Fonksiyonlar

Malumunuz fonksiyonlar (methodlar) bir programın eli kolu değildir ama programın hayata dokunması sürecidir. Fonksiyonlar doğru kullanılmazsa, çok yanlış anlaşılabilir, büyük felaketleri doğurabilir.  Buradaki ibret doğal olarak fonksiyonlar için de aynen geçerlidir.

Bir program bir problemi çözmek üzere bir takım işler yapacağından, programda işi yapan, haliyle fonksiyonlardır. Bu sebepten ötürüdür ki fonksiyon isimlerinin ve tanımlamalarının iyi yapılması, programın işini hakkı ile yapmasında yadsınamaz bir paya sahiptir. Bir fonksiyon okunduğunda, okuyan kişinin beyninde bağlantı kuracağı bir şeyleri uzun süreler aramamalı, hemen gideceği yere gitmelidir. Bu da fonksiyonu yazanın pekala da yardımcı olabileceği bir konudur. Çiçek gibi kod yazmanın bazı basit, temel kuralları vardır. Bu kuralların bazıları biliniyor bazılarını ben uydurdum. Aklınıza yatmayanı zaten boş veriniz. Söz konusu kurallar şöyle:

  • Fonksiyonun adı, fonskiyonun sorumluluğunu ve söz konusu mevzuyu çok^5 temizlik seviyesinde açıklamalıdır. Temizlik, isimden başlamaktadır.
  • Fonksiyon, mümkünse tek bir iş yapmalıdır. Mümkün değilse bile fonksiyon tek bir iş yapmalıdır.
  • Fonksiyon çok uzun olamamalıdır. Bir fonksiyonu okurken afedersiniz skrol yapmak gerekiyorsa,  o fonksiyon hemen parçalanmalıdır.21″ monitörde tek fonksiyon içine skrol gerektirecek kadar kod yazmak hol değildir.
  • Fonksiyon pahalı bir olgudur. Bu sebeple fonksiyonun tekrar kullanılacağı düşünülmelidir.
  • Yazılan bir fonksiyon, makine için değil insan için yazılır. Fonksiyon makine üzerinde çalışacak diye bir tek makinenin anlayacağı şekilde yazmak kalite ve anlaşılabilirlik kaybına sebep olur. Kod çalışmak zorunda olduğundan makine zaten onu anlayacaktır. Asıl mesele, insanın anlayacağı şekilde kod yazmaktır.
  • Fonksiyon, dağıtılmadan önce doğrulanmalıdır ki kullanan kişilere aktarılmasının bir manası olsun.
  • Kolaya kaçılıp, afedersiniz kötü kod, yorum satırlarıyla sıvanmamalıdır. Yorum satırları geçici iken, fonksiyonun kendisi kalıcıdır. Madem ki yorum satırı yazılabiliyor, ondan önce fonksiyonun kendisi temiz yazılmalıdır. Kod yazarak yapılamayacak şeyler, yorum satırları ile yapılmaldır.
  • Bir fonksiyonun adında -meclisten dışarı- “ve(and), veya(and), oyleyse(then)” gibi kelimelerin geçmesi, o fonksiyonun birden fazla iş yaparak dünyayı kurtarmaya çalıştığını göstermektedir. Bu çok yanlıştır. Dünyayı kurtarmak  bir takım işidir. Bu fonksiyonlar derhal parçalanmalı ve temizlenmelidir.
  • Bir fonksiyonu her kullanan kişi, o fonksiyonun tepesindeki yorumları değil, bizzat ismini görecektir. Yorum satırını görebilmek için fonksiyonun implementasyonunu açmak gerekmektedir. Bu, orta çağdan kalma bir işkence yöntemidir ve yapılmamalıdır. Reçete olarak, temiz, yaptığı işi ismiyle anlatan fonksiyonların yazılması şifa verecektir.
  • Bir yazılımdaki tüm isimler, derleyici tarafından adres sembollerine çevirileceğinden, uzun ve derdi açıkça anlatan fonksiyon isimleri seçmek hiç kimseye zarar vermeyeceği gibi yazarın yaptığı işin kalitesini artıracaktır. Uzun isimli fonksiyon, kısa isimli fonksiyondan daha fazla bellek tüketmeyeceğinden eli korkak alıştırmanın lüzumu yoktur.

Maddeler bunlar. Şimdi kalem kalem bu başlığın önemli konularına değinelim.

Anlaşılabilirlik ve Modülarite

Hiç laf kalabalığı yapmadan, somut örneklerle mevzuya dalacağım. Zaten eski bir ahitte yazdığım bir örneği sizlerle bu perspektifte paylaşacağım.

Kötü Örnek:

Yukarıdaki rezil kodu hatırlarsınız. Bu tür kodlama yüzünden nice çok da olumlu yorulmlar alınmayacağı anlaşılmakta. Bir kere fonksiyonun adından “Ve” yazıyor. Bu fonksiyon dünyayı tek başına kurtarma gayretini, belki iyi niyetle ancak saf bir cehaletle göstermektedir. Cehalet kötüdür. Fonksiyonun adı hele iyice faciadır çünkü C dilini az çok bilen herkes bu fonksiyonun iki değeri toplayarak, bellekte bir yerlere yazdığını anlayabilecektir. Asıl soru bu işin neden, ne zaman, ne amaçla yapıldığıdır ki bu da gerçeğin altındaki hakikatin ta kendisidir.

Bir diğer şık olmayan davranış ise fonksiyon isminin Türkçe, yorumların ise Almanca + İngilizce olmasıdır. Bu yorumları kimse – belki İlber Ortaylı hariç – anlayamayacaktır (İlber Hoca da yorumları anlasa da kodu anlayamayacaktır). Dolayısıyla kodda tek bir insan dili tercih etmek daha hoş olacaktır.

Güzel Örnek:

Bu yukarıdaki kod da tanıdık. Ama ben kodu yeni görmüş gibi, “aaa ne güzel kod O_o” demek istiyorum. Paralel evrenin, bu kodu içeren, pek de ücrada kalmamış bu güzel köşesinde, kötü örnek kodunda yapılan işler bu defa çiçek gibi tertemiz bir şekilde, amme hizmeti bilinci ile yapılmıştır.  Kötü örnekteki kod derin kod olduğundan ne iş yaptığı bilinmemekte idi. Güzel örnekteki kod temiz kod olduğundan, kodun aslında ticaret işleri ile uğraştığı anlaşılmaktadır.

Gönderilecek veri serileştirilmek zorunda olduğundan, union kullanılarak +1 mühendislik puanı kazanılmıştır.

Değişken adları da mevzu hakkında çok sayıda açık bilgiyi, yazılım tutkunlarının hizmetine sunmaktadır. Bu kodu okuyunca u16BazUcretTL’nin TL cinsinden, 65536 TL’den küçük bir meblağ olduğu anlaşılmaktadır. Bu da, kodlamada şeffaflık ve temizliktir.

Kötü kod, kötülükle sıkı bağlar kurmuştur. Seri porttan veri gönderme işi er ya da geç başka yerlerde de kullanılacağından, kötü örnekteki yapıda kopyala yapıştır yapmak gerekcektir ki bu tekrar kullanılabilirlik kavramından çok uzaktır. Güzel örnekte ise bu işi yapan bir fonksiyon, ayrı bir bireydir ve tekrar kullanılabilir yapıdadır. Yani benzetme yapılacak olursa; hem dünyası, hem ahireti güzeldir.

Rekürsif Fonksiyonların Kullanımı

Mümkünse kullanmayalım efendim. Stack derinliği sabit olmayan rekürsif fonksiyonlar, gömülü sistemlerde kullanılmamalıdır. Zaten ters gidebilecek bir sürü şey varken neden bir şey daha ekleyelim ki?

Sayın muhterem… Eveeeet, bir programın daha sonuna geldiik.

Şimdi devam!

Önceki Sayfa   Sonraki Sayfa

 

Gömülü C – 6 : Lezzetli Dosya Formatı

Opratörlerden sonra, sizlere de bizlere de bir nefes aldıracak bir konuya değineyim istedim. Kafalarımızı dinlendirmek için araya güzel bir konu sıkıştırıyorum. C dilinde yazılacak bir yazılım için dosya formatı nasıl olursa yakışıklı olur ona değineceğim. Malumunuz C’de, terbiyemizi takınarak yazdığımız yazılımlarda, uzantısına göre iki çeşit dosya oluyor: c ve h dosyaları. Bunların adam akıllı organizasyonu, seneler içinde edinilen bilgi ve tecrübeler vesilesiyle, ibretlik bilgiler içeren bir hal alıyor. Ben de bu bilgiyi burada sizlere aktarmaya çalışacağım.

Her yiğidin bir yoğurt yiyişi vardır demişler. Dosya formatı mevsusu da bu mevzuya epeyce benzer. Her yiğit yoğurdu başka yiyebilir ama güzel yoğurt her zaman güzel yoğurttur. Ben de güzel bir yoğurdu, kendi tarzımla sizlere sunacağım. Öyleyse haydi başlayalım!

Not:Bu vesileyle bu yazının temasının yoğurt olduğunu bilgilerinize arz etmek isterim.

Source (Kaynak) Dosyaları

  • Kaynak dosyalarının uzantısı: *.c olmalıdır. Örneğin yogurt.c
  • Dosya isminde Türkçe karakter kullanmazsanız, yoğurdunuz ekşimez.
  • Dosya adları açık ve anlaşılabilir olmalıdır. Dosya adını kısa yazmanın Murphy dışında kimseye bir faydası yoktur.
  • Dosya adı küçük harflerle başlamalıdır. Örneğin YaRaLiKaRiZmA34.c gibi ergen isimlendirmeleri ile yapılan yoğurttan cacık bile yapılmaz.
  • Dosyanın uzantısı da küçük c olamalıdır. ayran.C gibi isimlendirmeler, cehalete delalet eder. Yapmamak lazım, çirkinleşmeye hiç gerek yok.
  • Yerel, lokal, private(umumi olmayan) elemanlar statik tanımlanmalıdır.
  • Extern sözcüğü, yoğurttaki zararlı bir bakteri çeşididir. Onsuz da güzel yoğurt yapılabilir.

Çok güzel ahkam kestim ama farkındayım ki vakit, lafa karnı tok olan siz değerli okuyucuma lezzetli bir yoğurt sunma vaktidir.

Sevgili okuyucu, yukarıdaki kod şablonunu ingilizce yazdım ama lütfen kırılmayın darılmayın. İngilizce bilmiyorsanız bile çeviri ile anlamlarını öğrenmek çok çok kolay. Öyle kompleks şeyler yazmadım. Önceden dediğim gibi bir yazılımı yazarken tek bir insan dilinde yazmak lazım. Ben, terminoloji İngilizce olduğundan ve profesyonel hayatımda da kodları İngilizce istediklerinden formatı İngilizce olarak paylaşıyorum. Dana yoğurdu deyip Angus yoğurdu göstermiş olabilirim ama beni anlayacağınızı biliyorum. Kızmayın, darılmayın, trip atmayın.

Yukarıdaki formatı incelediğimizde, formatın sayısız ibretler içerdiğini görebilirsiniz. Bir kere başlıklar filan bir ilginç. Bazılarınıza bu güzel yoğurt tanıdık geldiyse dilinizin ucundaki sözcüğü ben söyleyeyim. DOXYGEN!!! Kanlıca yoğurdunu, pudra şekeri olmadan yemek nasıl tarihi bir hata ise, bir dosyadaki yorumları DOXYGEN’i sallamadan yapmak da o derecede talihsiz bir hatadır. Nitekim Doxygen ile yazan bir üstad’ın yoğurdu, camış yoğurdu gibi taş gibi olacaktır. Kodu yazan bu büyük üstad, kodun dökümantasyonunu da aradan çıkarmış olacaktır. Şimdi ben Doxygen dedim ama burada onu anlatmayacağım. Çünkü tonla kaynak var ve öğrenmek çok kolay. Sadece haberiniz yoksa, duyduysanız ama çok önemsemediyseniz diye bir değineyim istedim.

Yukarıdaki define satırı da aslında yoğurttaki zararsız bir bakteri gibi görünüyor ama aslında bu zararsız bakteri, sayısız hastalığa iyi gelir. Eğer modüler bir tasarım yaptıysanız her bir dosyayı bir mini modül gibi düşünmek isteyebilirsiniz. Bu yukarıdaki define size, bir modül projenizde var mı yok mu anlama imkanı sunar. Başka bir kaynak dosyasında #ifdef SAMPLE_C diyerekten o varsa şunu yap, yoksa da yoğurt yapmaktan vazgeçme bunu yap diyebilirsiniz. Bu gibi nice ibret, bu yoğurttaki bu bakterinin, faydalı bir bakteri olduğunu bizlere göstermektedir.

Devam edecek olursak, defines & macros kısmı görürüz. Bi dakka! Define ifadelerinin h dosyasında olması gerekmez mi? Evet ne yazık ki yanlışlıkla koymuşum onu C dosyasına demeyeceğim çünkü bunun da ibretlik bir sebebi var. bazı makrolar ya da define’lar, diğer modülleri de ilgilendirecek onların da işine yarayebilecek şeyler olduklarından, umuma hizmet açısından bu define’lar h dosyasına konur. Ama bazı makrolar, define ifadeleri de vardır ki, onlar yiğidin yatak odası gibidir, dışarı açılmaları hoş olmaz (?). Neyse konuyu saptırmayayım, tıpkı değişkenler ve fonksiyonlar gibi, makroları da dışarıya açmamayı seçebilirsiniz, bu durumda bu makrolar C dosyasında tanımlanır.  Mevzuyu daha da uzatmayacağım, anladınız siz onu.

Dosyanın geri kalanını çok detaylı açıklamayacağım. Static olan fonksiyonlar umuma açık olmayan fonksiyonlar oluyor. Yoğurdu yemek için içindeki bakterilerle tanışıp çay partisi yapmaya gerek yok. Static olan bu fonksiyonlar, modülün iç meseleleri. Static olmayanlarsa umuma hizmet olarak, dışarıya açılan elemanlar. Bunlar da yoğurdun kaymağı. Static olmayan fonksiyonların prototipleri, h dosyasında yer alacak. Fonksiyon prototipini yazmak, derleyiciye “bak haberin olsun bro, böyle bi fonksiyon var sonra duymadım etmedim deme” demek olduğundan, umuma duyurulacak fonksiyonların prototipleri doğal olarak h dosyasında yer alır. Static fonksiyonların prototipleri de c dosyasında yer alır. Static fonksiyon prototipinin h dosyasında yer aldığı durum da vardır ve ibretlik bir durumdur ama çok çok istisnai olduğundan onu yok saymak hakkımızdır. Nedenleriniz çok kuvvetli değilse yapmayın etmeyin. Kanlıca yoğurdu gibi dosya formatı var. Monalisa tablosunun kopyası gibi, al evine duvarına as.

Header (Başlık) Dosyası

  • Başlık dosyalarının uzantısı: *.h olmalıdır. Örneğin yogurt.h
  • Kaynak dosyalarının isimlendirilmesindeki maddeler, 2. maddeden itibaren aynen geçerlidir.

Yukarıdaki başlık dosyasının hikmetlerinin bir çoğunu artık anlayabiliyorsunuz. Bir tek aşağıdaki kısmı açıklayayım:

Bazen, dostlar; bir kaynak dosyası istemeden de olsa aynı header dosyasını iki defa çağırabilir. Örneğin bizim kaynak dosyamız olan cacik.c, yogurt.h ve hiyar.h’ı include etsin. Eğer hem yogurt.h hem de hiyar.h dosyaları içerde yemek.h dosyasını include ediyorsa, bizim cacik.c aslında yemek.h dosyasını iki defa include etmiş olur. Bu da çok tatsız bir yoğurt yiyiş şeklidir ve besin zehirlenmesine sebep olabilir. Bunu engellemek için yukarıdaki ifdef yapısı kullanılır. Bu durumda header dosyası iki defa çağırılsa dahi ilk çağırmada defined olmayan H_SAMPLE, defined olacağından bir daha bu header dosyasının içine girilmez yani aslında bu header iki defa include edilemez. Bu da bir yiğide yakışan bir yoğurt yeme şeklidir.

Bendeniz, zat-ı alilerinize, dosya formatları hususundaki bakışımı aktardım. Artık bunu yorumlamak veya ilerletmek sizlere kalmış. Yazıyı okuduğunuz için teşekkürler 🙂

Şimdi devam…

Önceki Sayfa   Sonraki Sayfa

 

Gömülü C – 5 : Operatörler

Önceki yazılarda, bir C programı hakkında feyizli bir takım konular üzerinde konuşmuştuk. Merhaba dünya yazılımının anatomisinden sonra ibretlik veri tiplerini, değişkenler ile onlara atanacak sabitleri, ardından da alımlı kodun olmazsa olmazı yorum satırlarını incelemiştik. Bu defa ise, C dilindeki bir diğer önemli başlık olan operatörleri inceleyeceğiz.

Dünyada çeşit çeşit operatör vardır ancak ne mutlu bize ki C dilindeki operatörler çeşitleri sınırlı sayıda. 🙂 Neyse, “operatörlere özgü bir yazı” olması, ilk bakışta biraz garip guraba gelebilir ama, operatörler özellikle gömülü programlamada “çok bilinçli şekilde kullanılmak zorunda” olduğundan değer verilmesi gereken önemli bir konu. Bizim de niyetimiz operatörlerin hak ettiği saygınlığı kazanmasına yardımcı olabilmek.

Bazen aynı amaç, farklı operatörler ile gerçeklenebilir. Hatta genelde durum böyledir. Bu aşamada, hangisini seçmenin daha akıllıca olacağına karar vermenizi sağlayacak birtakım ince noktalara burada değinmeye çalışacağım. Operatörlerin doğru kullanımında dahi bazı kazan/kaybet (trade-off) durumları olduğundan, yine ibretlerle dolu bir yazının şanlı başlangıcında olduğumuzu hissediyorum. Haydi hayırlısı…

Aritmetik Operatörler

C dilinde aritmetik operatörler, bizleri çocukluğumuza, ilkokul sıralarına götürür 🙂

Not: Operatörlerin uygulandığı değişken veya sabitlere genel olarak operand denebilir. A=10, B=20 için;

Operatör Tanım Örnek
+ iki operandı toplar A + B = 30
Soldaki operanddan sağdaki operandı çıkarır. A – B = -10
* operandları çarpar A * B = 200
/ soldaki operandı sağdaki operanda böler B / A = 2
% Mod operatörü, bölmeden sonra kalanı verir B % A = 0
++ Bir artırma operatörü A++ = 11
Bir azaltma operatörü A– = 9

Aritmetik operatörleri etkin şekilde öğrenmenin en iyi yolu, bu operatörleri kullanarak programlar yazmak ve bunları çalıştırarak sonuçları görmektir. Benim derdim, operatörlerin ne iş yaptığını anlatmak olmamalı diye düşünüyorum. Herhangi bir C dersinde/kitabında bu zaten alenen anlatılıyor. Aşağıdaki örnek yazılımı yazmamın ardından asıl anlatılması gerken ince noktalara geçeceğiz.

Yukarıdaki kod çalıştırıldığında, çıktısı aşağıdaki gibi olur:

Toplama: 30.000000 Cikarma : -10.000000 Carpma: 200.000000 Bolme: 0.500000 Mod: 10
++ sonra kullanilinca i:30
bir sonraki adimda i:31
++ once kullanilinca i:31
bir sonraki adimda i:31

Önemli bir nokta olarak i++ yazdırıldığında, önce i’nin değerinin yazdırılıp ardından bir artırıldığında dikkat ediniz. Aynı şekilde ++i yazdırıldığında, önce i’nin değerinin bir artırıldığında ardından bu değerin yazdırıldığına çok dikkat ediniz. İnananlar için burada büyük ibretler var. ++ opratörünü bu bilinçle kullanmakta faydalar var.

Aritmetik operatörlerle ilgili önemli bir diğer nokta da öncelik sırası kavramı. Öncelik sırasına takılmamak ve kodu okunur kılmak adına, ardışıl aritmetik işlemlerde parantez kullanaraktan sorunu teğet geçmekte fayda var. Örneğin 13+227-12/3 ile ne demek istediğimi anlayamayabilirsiniz, demek istediğimi yanlış diyor da olabilirim ama 12+(227)-(12/3) ile ne demek istediğimiz çok açık olur. C dilinde malum her zaman parantezin içi öncelikli oluyor. Hem hataları önlemek için hem de toplum içerisinde anlaşılabilir olmak için bu alışkanlığı edinmekte faiderler, feyizler var.

Aritmetik operatörlerle ilgili bir diğer önemli nokta da, yerli yersiz kullanılmamaları. Kimi zaman (hatta çoğu zaman), bir işi yapmanın birden fazla yolu oluyor. Örneğin 8 bitlik iki sayıyı alıp yanyana koyup 16 bitlik tek bir sayı elde etmek istediğimiz yerler oluyor. Bunu yapmak aşağıdaki şekillerde mümkün:

Bazı platformlarda toplama, çarpma gibi aritmetik işlemler atomik değildir, yani bu operatörlerin işletilmesi 1 saat darbesi süresinden (1 cycle) fazla sürer. Halbuki her işlemcide AND,OR işlemleri tek cycle’da yapılır. Buna göre eğer yukarıdaki kodu MSP430 serisi mikrokontrolörler için yazıyorsanız, yöntem 0 sizi canınızdan bezdirir çünkü eğer HW multiplicator olmayan bir modelde çarpma 130 cycle kadar sürer, HW multiplicator olan bir modelde bile çarpma 8 cycle sürer. Daha bunun toplaması ve ataması da var. Halbuki Yöntem 3’te tüm olay hepi topu 3 cycle’da biter. Yöntem 4’ün ise çok sanatsal bir amacı var, umarım anlamışsınızdır ancak anlamadıysanız dahi ileride detaylıca anlatacağım zaten.

Neyse demek ki yerli yersiz aritmetik operatör kullanmamak lazımmış. Gerçi Arm Cortex M3 mimarisinde aritmetik operatörler de 1 cycle sürüyor (non-fp için). Orada elinizi korkak alıştırmayabilirsiniz ama yine de gün gelir o kodu 8 bitlik bir mikrokontrolöre taşımanız gerekirse başınız ağrır. En güzeli, en baştan çiçek gibi bilinçle yazmak 🙂

İlişkisel Operatörler/ Karşılaştırma Operatörleri

İlişkisel operatörler sağ ve solundaki operandlar belirli bir mantıksal ilişkiye göre karşılaştırılır ve eğer ilişki doğru ise doğru döndürülür, yanlışsa yanlış. 😀

Operatör Tanım Örnek
== İki operand birbirine eşitse, sonuç doğru(true,1) olur (A == B)
!= İki operand birbirine eşit değilse, sonuç doğru(true,1) olur (A != B)
> Soldaki operand sağdakinden büyük ise, sonuç doğru(true,1) olur (A > B)
< Soldaki operand sağdakinden küçük ise, sonuç doğru(true,1) olur (A < B)
>= Soldaki operand sağdakinden büyük ya da eşit ise, sonuç doğru(true,1) olur (A >= B)
<= Soldaki operand sağdakinden küçük ya da eşit ise, sonuç doğru(true,1) olur (A <= B)

Bu kısımla ilgili verilecek ibretlik mesajı önceki kısımlarda vermiştik. Ancak tekrar bir hatırlatma yapmak gerekirse;karşılaştırma operatörleri genellikle if,while gibi koşul/döngü işlemlerinde kullanılır ve doğal olarak en çok hata da buralarda yapılır. Örneğin sık yapılan hatalardan biri if(age == 18)  yazacakken yanlışlıkla if(age=18) yazmaktır. Bu durumda age değişkenini 18 ile karşılaştırmak yerine, age değişkenine 18 atamış ve dönüş olarak true almış olursunuz. If içinde atama yapmak mümkün olduğundan derleyici buna hata vermez, uyarı verebilir. Bu hatayı hiç yapmamanın yolu if(18 == age) formatını kullanmaktır. Yani sabiti sola, değişkeni sağa almaktır. Bu durumda yanlışlıkla if(18 = age) yazsanız bile, derleyici size sabite değişken atanmaz diye hata verir. Bu arada 18 yazdım ama, örnek anlaşılsın diyerekten sayıyı doğrudan yazdım 🙂 Yoksa MAGIC_NUMBER kullanmak yok 😉 Önerdiğim formatta yazacak olursam eğer if(ageOfDriverCandidate == AGE_LIMIT_TO_DRIVE) yerine if(AGE_LIMIT_TO_DRIVE == ageOfDriverCandidate) yazmakta fayda var. Ya da bu hususta sık hata yapıyorsanız, bir makro yaratarak, ve onu bir kez test ederek bu sorunu tarihin tozlu sayfalarına gömebilirsiniz :

 

Mantıksal Operatörler

Bazen birden fazla koşul aynı anda değerlendirilmek istenebilir. Bu durumda mantıksal ilişkiye göre (ve,veya,değil) koşullar değerlendirilebilir.

Operatör Tanım Örnek
&& Mantıksal VE(AND) operatörü çağırılır. Eğer iki taraf da sıfırdan farklı ise, sonuç doğru(true) olur. (A && B)
|| Mantıksal VEYA(OR) operatörü çağırılır. Eğer iki taraftan herhangi biri sıfırdan farklı ise, sonuç doğru(true) olur. (A || B)
! Mantıksal DEĞİL(NOT) operatörü çağırılır. Operandın mantıksal tersi alınır; operand 1 ise sonuç 0, operand 0 ise sonuç 1 olur. !(A && B)

Mantıksal operatörler birleştirilerek kullanılabilir. Ancak insan aklının almayacağı uzunlukta bir koşul söz konusu ise, o koşul ya indirgenmeli, ya da yorum satırları ile açıklanmalıdır. İnsan aklı derinlik olarak ortalama 7 seviye ilişkiye kadar hafızada tutabilir. Fazlası olmaz 🙂 if içinde 9 tane koşul yazmamakta fayda var.

Bitsel/İkili (Bitwise/Binary) Operatörler

Esasen bitsel operatörlerin ciğerini BURADA, çiçek gibi açıkladık. Hatta elektronik olarak nasıl gerçeklendiğini de konuştuk. Ancak tabi ki olayı bir de yazılım perspektifinde incelemekte sayısız feyizler var. Zira gömülü sistemlerde kimi zaman bir bitin bile hesabı yapılır. Hesabının yapılmadığı yerde bile, kullanılan mikrokontrolörün bir registerındaki bir biti 1 ya da 0’a çekmek için bitsel operatörler kullanılabilir. Bu söylediğim ilk aşamada bir anlam ifade etmemiş olabilir, ancak ileride değineceğimiz üzere mikrokontolördeki donanımı kullanabilmek için, genişliği genelde işlemcinin adres yolu genişliği kadar olan (8/16/32 bit), ayırılmış özel bellek alanlarına (register) bir takım veriler yazmak gerekir. Belleği verimli kullanmak için bir register içindeki her bitin ayrı ayrı işlevi olur. Bu nedenle registerlara bitsel olarak erişmek gerekir. Burada da genellikle bitsel operatörler kullanılır. Yani mevzu, o kadar önemli ki, ateş ediyor =)

Misal A = 60; ve B = 13; olsun. Bunların ikili tabanda gösterimi şöyle olur:

A = 0011 1100

B = 0000 1101

Buna göre

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A  = 1100 0011

Operatör Tanım Örnek
& Bitsel VE Operatörü (A & B) = 12, yani 0000 1100
| Bitsel VEYA Operatörü (A | B) = 61, yani  0011 1101
^ Bitsel XOR Operatörü (A ^ B) = 49, yani  0011 0001
~ Tümleyen operatörü. Operandın 1 olan bitlerini 0, 0 olan bitlerini de 1 yapar. (~A ) = -61, yani  1100 0011
<< Sola kaydırma operatörü. Soldaki operandın bitleri, sağ operand kadar sola kaydırılır ve her kaydırmada en sola 0 eklenir. (Karışık oldu, örnek üzerinden görmekte fayda var) A << 2 = 240 yani 1111 0000
>> Sağa kaydırma operatörü. Soldaki operandın bitleri, sağ operand kadar sağa kaydırılır ve her kaydırmada en sağa 0 eklenir.(Karışık oldu, örnek üzerinden görmekte fayda var) A >> 2 = 15 yani 0000 1111

Şimdi gelelim fasülyenin faydalarına 🙂 Yani her yerde yazmayan önemli bilgilere…

& (VE) operatörü ile maskeleme yapılarak bir sayının 1 olan bitlerini 0’a çekmek yani temizlemek mümkündür. Misal:

 

| (VEYA) operatörü ile maskeleme yapılarak bir sayının 0 olan bitlerini 1’e çekmek yani set etmek! (kurmak) mümkündür. Misal:

^ (XOR) operatörü candır! Bu operatör ile maskeleme yaparak bir sayının herhangi bir bitini (ya da bitlerini) terslemek mümkündür.

Ek olarak kaydırma operatörünün, cyclic olup olmadığı her platformda mutlaka test edilmelidir. Normalde cyclic olmaz, ama test etmekte fayda var =)

Yazdığım örneklerde zaten kaydırma operatörünün kullanımı da var. Bir de ^=, +=, |= gibi örneklerden atama operatörünün diğer bitsel ve aritmetik operatörlerle birleştirilebildiğini de göstermiş olduk diye düşünüyorum.

Bu gün bu yazımı Mustafa Keser üstadımızın sözü ile sonlandırıyorum.

“Eveeeeet, bir proğramın daha sonuna geldiiik. Tekrar görüşmek üzere efeem.”

 

Önceki Sayfa   Sonraki Sayfa