bitsel işlemler – 2

Özellikle alt seviyeli kodlarda bir tamsayının bitleri üzerinde bazı işlemlerin yapılması (bitwise manipulation) sıklıkla gerekli olur. En sık yapılan bitsel işlemler şunlardır:

bir tamsayının belirli bir bitinin birlenmesi
Buna tamsayının belirli bir bitinin “set edilmesi” de denir. Bir tamsayının belirli bir bitini birlemek için, tamsayı ilgili biti 1 olan ve diğer bitleri 0 olan bir sayıyla “bitsel veya” işlemine sokulmalıdır. Çünkü bitsel veya işleminde 1 yutan eleman 0 ise etkisiz elemandır. Aşağıdaki koda bakalım:

Yukarıdaki kodda ch değişkeninin 5. biti birleniyor:

x bir tamsayı, n de bu sayının herhangi bir bitinin indeksi olmak üzere bir tamsayının n. bitini birleyecek bir ifade şu biçimde yazılabilir:

Bu tür bitsel işlemlerde kullanılan bitleri manipüle etmek için kullanılan

gibi ifadelere “bitsel maske” (bitmask) denir.

bir tamsayının belirli bir bitinin sıfırlanması
Bir tamsayının belirli bir bitini sıfırlamak (clear / reset) için tamsayı, ilgili biti 0 olan ve diğer bitleri 1 olan bir maskeyle “bitsel ve” işlemine sokulur. Çünkü “bitsel ve” işleminde 0 yutan eleman 1 ise etkisiz elemandır. Bu bitsel maske aynı biti birlemekte kullanılan maskenin bitsel değilidir. Aşağıdaki örnekte bir tamsayının 5. biti sıfırlanıyor:

x bir tamsayı, n de bu sayının herhangi bir bitinin indeksi olmak üzere, x tamsayısının n. bitini sıfırlayan bir ifade aşağıdaki gibi genelleştirilebilir:

bir tamsayının belirli bir bitini değiştirmek
Bazı kodlarda bir tamsayının belirli bir bitinin değiştirilmesi (toggle – flip) gerekir. Yani söz konusu bit 1 ise 0, 0 ise 1 yapılmalıdır. Bu amaçla “bitsel özel veya” işleci kullanılır. Bitsel özel veya işlecinde 0 biti etkisiz elemandır.
Bir sayının n. bitinin değerini değiştirmek için, sayı, n. biti 1, diğer bitleri 0 olan bir maske ile “bitsel özel veya” işlemine sokulur. x, bir tamsayı, n de bu sayının herhangi bir bit numarası olmak üzere, x tamsayısının n. bitini ters çeviren bir ifade şu şekilde yazılabilir:

bir tamsayının belirli bir bit değerinin elde edilmesi (0 mı 1 mi)
Bir tamsayının belirli bir bitinin 01 mi olduğunun öğrenilmesi için, söz konusu tamsayı, ilgili biti 1 olan ve diğer bitleri 0 olan bir maskeyle “bitsel ve” işlemine sokulmasından elde edilen değer mantıksal olarak yorumlanmalıdır. Çünkü “bitsel ve” işleminde 0 yutan eleman, 1 ise etkisiz elemandır. İfadenin lojik değeri “dogru” olursa, ilgili bit 1, yanlış ise ilgili bit 0 demektir. x bir tamsayı, n de bu tamsayının herhangi bir bitinin indeksi olmak üzere x tamsayısının n. bitinin 1 ya da 0 olduğunu sınayan bir deyim aşağıdaki biçimde yazılabilir:

Bir pozitif tamsayının tek sayı olup olmadığı “bitsel ve” işleciyle sınanabilir. Bir tamsayı tek sayı ise sayının 0. biti 1‘dir.

birden fazla bit üzerinde işlem yapmak
Bir tamsayının belirli bitlerini sıfırlamak için ne yapılabilir? Örneğin int türden bir değişkenin 7. , 8. ve 9. bitlerini, diğer bitlerin değerlerini değiştirmeden sıfırlamak isteyelim. Bunu gerçekleştirmek için, tamsayı 7., 8. ve 9. bitleri 0 olan diğer bitleri 1 olan bir maske ile bitsel ve işlemine sokabiliriz. Örneğin int türünün 16 bit olduğu bir sistemde bu maskenin ikilik sayı sistemindeki gösterimi aşağıdaki gibidir:

Bu tamsayının onaltılık sayı sisteminde gösterimi

biçimindedir, değil mi?

Şimdi de bir tamsayının bitlerini standart çıkış akımına yazdıran showBits isimli işlevi tanımlayalım. Sayının ilk olarak en yüksek anlamlı bitini yazdırmalıyız, değil mi?

showBits işlevinde i değişkenine tamsayının bit sayısının bir eksiği ile ilk değer veriliyor. Örneğin 32 bitlik int türü için i değişkeni 31 değeriyle hayata başlayacak. i >> 31 ifadesini 1 değeri ile bitsel ve işlemine sokarak sayının 31. bitinin 1 mi 0 mı olduğunu öğreneceğiz.
Aşağıda aynı işi değişik farklı bir biçimde yapan showBits2 isimli işlevi tanımlıyoruz:

Bu kez maske olarak kullanılacak en yüksek anlamlı biti 1 diğer bitleri 0 olan bir tamsayı ile başladık. Döngünün her turunda maskemizi sağa bir pozisyon kaydırdık. Böylece maskemiz içinde bulunan 1 biti döngünün her turunda x‘in farklı bir bitine karşılık geldi.

Alt seviyeli kodlarda sık yapılan bir işlem bir tamsayının kaç bitinin 1 olduğunu saptamaktır. Birçok uygulamada bu işlemin çok hızlı yapılması gerekir. İşlev çağrılarının oluşturacağı ek maliyetten kaçınmak için 32 bitlik bir tamsayının kaç bitinin 1 olduğunu hesaplayan kodu bir işlevsel makro (function-like macro) tanımlıyoruz:

Kod dosyamızda tanımlanmış olan 256 öğeli asbc dizisi bir arama tablosu (lookup table) olarak kullanılıyor. Bu dizinin n indisli öğesinin değeri n tamsayısının kaç bitinin bir olduğu bilgisi. Örneğin dizinin 15 indisli öğesinin değeri 4. Çünkü 15 tamsayı değerinin 4 biti 1.
Böylece bir byte değerini bu diziye indis yaptığımızda o byte’ın kaç bitinin 1 olduğunu bu tablodan elde edebiliyoruz. 32 bitlik bir tamsayı toplam 4 byte’a sahip olduğu için her bir byte için 1 olan bit sayısını ayrı ayrı bu tablodan bakarak buluyor ve bu değerleri topluyoruz.
Bir tamsayının düşük anlamlı byte‘ını tamsayı değeri olarak elde etmek için tamsayıyı 255 değeriyle bitsel ve (&) işlemine sokmamız gerekiyor. 32 bitlik tamsayımız x
değerinde olsun.
Şimdi de bir tamsayının 2‘nin kuvveti olup olmadığını sınayan bir işlevsel makro yazacağız. 2‘nin tüm kuvvetlerinin yalnızca tek bir biti 1‘dir. Bu durumda n bir tamsayı olmak üzere 2‘nin n. kuvvetinin 1 eksiği n. bitinden daha küçük indisli bitleri 1 diğer bitleri sıfır olan sayıdır.
Örneğin 2‘nin 5. kuvveti için
Bu durumda eğer bir sayı 2‘nin kuvveti ise, bu sayının kendisi ile bir eksiğinin bitsel ve işlemine sokulması durumunda 0 değeri elde edilmelidir. 0 tamsayısı 2‘nin kuvveti olmamasına karşın bu kurala uyar. Bu yüzden makromuzda tamsayının 0 olması olasılığını da göz önüne alıyoruz:
Share

Necati Ergin

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

Bunlar da ilginizi çekebilir

Kod Eklemek İçin Okuyun
Eklemek istediğiniz kodları lütfen aşağıdaki “pre” kodları arasında yazınız.
<pre class="lang:c++ decode:true ">
--yazacağınız kodlar--
</pre>
(buradan kopyalayarak kullanabilirsiniz)