Temel C Programlama -48- Bit Alanları ve Enümeratörler

C programlama dilinin diğer konuları arasında yer alan bit alanı (bit field) ve enümeratör (enumeration) konularını bu yazıda anlatacağız. Normalde baktığımızda çok da gerekli olmayan ayrıntı konularmış gibi görünse de bunlar ileri seviye C programlamada bize yardımcı olmaktadır. Acemi biri pek sık kullanmasa da ileri seviye programlarda ve kütüphanelerde karşımıza çıkmaktadır. O yüzden başta sık kullanacak olmasak da bunları bilmemiz, karşımıza çıkacak kütüphaneleri anlamamız yönünde önemlidir.

Bit Alanları

Ben bit alanlarına kitaptan baktığımda performansı artırmak için teferruattan ibaret olduğunu ve karşıma pek sık çıkmayacağını düşünüyordum. Ama ne zaman STM32 için CMSIS kütüphanesini incelediysem o zaman bit alanlarının en alt seviye programcılıkta bile kullanıldığını gördüm. Aşağıda bit alanlarının kullanıldığı bir kütüphanedeki örnek kod parçasını görebilirsiniz.

Bit alanları kısaca belli bir bit genişliğinde veri tanımlamak ve o verileri hafızada bir yere sığdırmak demektir. Örneğin biz bir değer için 16 bitlik bir değişken tanımlarken 16 bit içerisinde 4 adet 4 bitlik değer tanımlayıp saklayabiliriz. Yani değişken içerisinde birden fazla küçük değişkeni saklama işlemine bit alanı denmektedir. Bu hafızadan tasarruf etmemizi sağlamaktadır. Örnek bir bit alanı kodu şöyle olabilir.

struct 
{
uint32_t rezerve:24;
uint32_t ayar_biti:2;
uint32_t bayrak_biti:2;
uint32_t kontrol_biti:2;
uint32_t kesme_biti:2;

} zamanlayici_yazmaci;

Burada elimizde 32 bitlik bir bellek bölümü olsun. Bu bellek bölümü eğer özel fonksiyonların yürütüldüğü bir bölümse SFR (Special Function Register) yani özel fonksiyon yazmacı olarak da adlandırılabilir. Biz bu değişkende bazı konumda yer alan bitleri değiştirdiğimiz zaman özel fonksiyonlar yürütülmektedir. Mesela bir sistemdeki kesmeleri denetlemek istediğimizde 32 bitlik değişkendeki son iki biti denetlememiz gereklidir. Yani 0x11, 0x00, 0x10 ya da 0x01 değerlerini kullanabiliriz. Bu dört değer için koca bir 32-bitlik yeri işgal etmeye gerek var mıdır? Bu durumda bit alanları vasıtasıyla 32 bitlik veri alanında kendimize 2 bitlik bir yer açarız. Yukarıda uint32_t kesme_biti:2; komutunda bunu yaptık. Bit alanları bu yüzden gömülü sistemlerde oldukça kullanışlı olmaktadır. Çünkü gömülü sistemlerde bazen bir hafıza yerinde pek çok fonksiyon yer alabilir. Sürekli bunlar üzerinde farklı değişkenlerin değerini maskeleme yöntemi ile aktararak çalışmak yerine doğrudan bit alanları ile 32 bitlik yazmaç verisi üzerinde çalışma imkanına sahip oluruz. Üstelik struct olarak yapı değişkeni yaptığımız için pek çok aynı iskelet üzerine kurulmuş farklı yazmaçları bu şekilde kontrol edebiliriz.

Bit alanlarını CMSIS kütüphanesini incelediğim vakit uygulamalı olarak göstereceğim. Şimdilik sadece bu kadarını bilmeniz yeterli.

Enumeratörler

Enumeratörler bir değişkenin değerlerini adlandırma yöntemidir. Böylelikle program içinde değişkenin değerleri ile değil o değerlere karşılık gelen adlar ile işlem yapma imkanımız olur. Enümeratörlerin kullanım sebebi tamamen kolaylık sağlama adınadır. Sayısal olan değerleri sözel olan değerlerle değiştirerek program daha yüksek seviyeye çıkarılmaktadır. Örneğin ay adında bir değişkenimiz olsun ve bu ay verisi içersin. Elbette bu ay verisi sayısal olmak zorunda olduğu için Ocak, Şubat şeklinde değil 0, 1 … şeklinde temsil edilmek zorundadır. Bir değişkene Ocak, Şubat, Mart … diye değer atayıp bu değerler üzerinde kontrol ve aritmetik işlem yapmak o kadar kolay değildir. Eğer karakter dizilerinden bahsediyorsanız o apayrı bir seviyededir ve beraberinde türlü zorluklar getirmektedir. Bu yüzden program yazarken temsil edilmek üzere enümeratörler kullanılmaktadır. Bir örnekle size gösterelim.

enum aylar 
{
OCAK, SUBAT, MART, NISAN, MAYIS, HAZIRAN, TEMMUZ, AGUSTOS, EYLUL, EKIM, KASIM, ARALIK
};

// Tanımlama 

enum aylar ay1, ay2;

Burada aylar tipinde bir değer dizisi tanımladık ve değer olarak kendisine OCAK, SUBAT, MART, NISAN, MAYIS… diye giden değerleri verdir. Bu değerlerin hepsi birer ilizyondur! İşin aslınca OCAK = 0, SUBAT = 1, MART = 3 … diye giden değerlere sahiptir. Yani biz burada OCAK yazdığımızda 0 yazmaktan başka bir şey yapmamış oluyoruz. Bu değerler printf gibi fonksiyonlarla yazdırıldığı zaman gerçek sayı değerlerini göstermektedir. Fakat biz program yazarken kolaylık olsun diye ay1 = OCAK; yazabiliriz. Bu durumda ay1 değerine 0 aktarılmaktadır. Ayrıca bu değer üzerinde aritmetik veya mantık işlemleri de yapabiliriz. Bu sadece program yazarken bize kolaylık sağlamakta ve verilerin konuşma diline daha yakın sembolleri ile program yazma yolu açılmaktadır.

Kullanmak şart mıdır? Elbette hayır. Fakat programın daha okunur olmasını ve kolay anlaşılmasını istiyorsanız kullanabilirsiniz. Ben şahsen bu tarz şeyler için önişlemci direktifi olan #define tanımlamasını kullanmaktayım. Böylelikle hafızada herhangi bir yer işgal edilmemiş oluyor.

Last updated