|  | 
        
            | 
                    
                        | Yapılar, Birlikler ve Bit Alanları |  |  
                        | 
	
    
		
            | Gönderiliyor lütfen bekleyin... | 
 |  | 
        
            | Bu makalemde yapı, birlik ve bit alanları ile ilgili 
tanım,tanımlamalar ve örnek uygulamalar üzerinde duracağım. C dilinde int, float, 
char vb. ilkel veri tiplerimiz olduğu gibi bir çeşit kendi veri tipimizi tanımlama 
olanağımız da vardır. Bu tanımlamayı da struct anahtar sözcüğümüz ile gerçekleştirebiliyoruz. 
Küçük bir örnek vermek gerekirse: 
 
 
  Şeklinde olacaktır. 
    | struct ornek{ int a;
 char b;
 float c;
 };
 |  
 Yapımızın yapısını incelersek struct anahtar sözcüğü ve örnek adında bir yapı 
  etiketi kullandık. Her yapı ‘;’ ile bitmek zorundadır. Yapıların boyutu ise 
  içindeki veri tiplerinin toplam boyu kadardır. int,float ve char veri tiplerimizin 
  sırayla 2,4 ve 1 byte büyüklüğünde bellekte yer kapladıklarını düşünelim (Farklı 
  derleyiciler de farklı temel veri tipi boyutuna rastlamak mümkün), o zaman struct 
  örnek adındaki veri tipimizin toplam boyutu 7 byte olacaktır. Not: Alignment 
  kavramı göz ardı edilerek 7 byte olacağı farzedilmiştir. Eğer alignment parametresi 
  ile programımızı derlersek bir hizalama olacağı için göz önüne aldığımız sistemde 
  7byte yerine 8 byte yer kaplayacaktır. Alignment gerçekten programımızı hızlandıran 
  bir seçenek olarak karşımıza çıkar ve CPU nun daha az yorulmasını sağlar. Eğer 
  yapımızı bir veri tipi olarak düşünürsek fonksiyonlara parametre olarak göndermek 
  ve geri dönüş değeri kullanmak bizim için daha da kolay bir hal alacaktır. Yapıların 
  fonksiyonlarla kullanılmasına ve genel kullanımına ilişkin bir senaryo oluşturalım. 
  Senaryomuz, iki tane farklı yapının farklı bellek bölgelerine kopyalanması olacaktır 
  ve bunu bir fonksiyon yardmıyla gerçekleyecektir.
 
 İlk önce yapı tasarımımızı oluşturalım:
 
 
 
  Burada typedef anahtar kelimesi sayesinde uygulamamızda veri 
tipimizi kadir adında kullanabilmekteyiz. Yapımızın boyu 32 byte’dır. Kullandığımız 
uygulamalarda direk hesaplamak yerine sizeof(kadir) veya sizeof(struct etiket_ismi) 
şeklinde de öğrenebilriz. 
    | typedef struct{ char ad[15],
 soyad[15];
 int borc;
 }kadir;
 |  Fonksiyonumuz ise:
 
 
 
   
    | kadir *kopy(kadir *al){ rewind(stdin);
 puts("String gir");
 gets(al->ad);
 puts("2. String gir");
 gets(al->soyad);
 puts("rakam gir");
 scanf("%d",&al->borc);
 return al;
 }
 |  Şeklinde olsun.Burada kopy adındaki fonksiyonumu parametre 
olarak kadir tipinden bir adres beklemektedir. kadir isimli veri tipimizi de typedef 
ile yapımız üzerinde tanımladık. Fonksiyonumuzun geri dönüş değeri ise yine kadir 
tipinden bir adres olacaktır. rewind(stdin) ile standart input’umuzu geriye sardık. 
Ve puts fonksiyonları ile bir adres yazdırdık. Dikkat edilmesi gereken yer ise 
gets fonksiyonumuz parametre olarak yolladığımız kadir tipinden al adında değişkenin 
elemanlarına ‘->’ işaretiyle ulaşıyoruz. Eğer işaretçi üstünden değil de direkt 
değer türünden oluşturmuş olsaydık ‘.’ İşaretiyle elemanlarımıza ulaşabilirdik(Örnek: 
gets(al.ad); ) . scanf fonksiyonumuzun ise geleneksel olarak okuttuğumuz temel 
veri tiplerinden farklı bir yazım olarak sadece &borc olması gereken yerde 
&al->borc şeklinde yazılmıştır. Son olarak da kadir tipinden al adresini 
döndürüyoruz. main fonksiyonumuz ise şöyle olmalıdır:
 
 
 
  
    | int main(void) {
 kadir *x1;
 kadir *x2;
 clrscr();
 x1=(kadir *)calloc(sizeof(kadir),5);
 x2=(kadir *)calloc(sizeof(kadir),5);
 for(int j=0;j<5;++j) {
 *(x2+j)=*(kopy(x1+j));
 }
 for(int r=0;r<5;++r){
 puts((x2+r)->ad);
 puts((x2+r)->soyad);
 printf("%d",(x2+r)->borc);
 }
 getch();
 return 0;
 }
 |  kadir tipinden iki adet işaretçi tanımladık ve bunlara calloc fonksiyonu ile 
  sizeof(kadir)*5 kadar yer aldık yani toplamda 5’er adet yapımız için yer açtık. 
  Eğer sizeof() işlecini kullanmasaydık ‘(kadir *)calloc(32,5);’ da diyebilirdik. 
  Ardından for döngümüzü 5 kere dönecek şekilde kurduk ve içinde kopy fonksiyonumuzu 
  çalıştırdık. x1+j adresini fonksiyona parametre olarak verdik(x1+0,x1+1,…x1+4 
  olarak parametreler gidecektir) ve geri dönüş değerimizi işaretçi olduğu için 
  onun * operandıyla değerini *(x2+j) nin gösterdiği adresinin değerine yerleştirmiş 
  olduk.
 
 Not: Yapı işaretçilerinin 1 adres ileri gitmesi yapının boyu kadar olur. Diyelim 
  yapımız 64 byte biz adresimizi bir arttırdığımızda 64 byte ileri gider. Veya 
  4 adres ileri gidersek 64*4 kadar yani 256 byte kadar ilerlemiş olur.
 Bu şekilde x1 adresimize bilgileri kopy fonksiyonuyla 
  okuyup yine sırasıyla x2 ye yerleştirmiş olduk. Adresler hakkında ki bilgi ve 
  RAM’lerdeki yerleşimleri için alttaki resmi inceleyebilrisiniz.
 
 
  İkinci for döngümüzde ise 
  x2+r diyerek sırasıyla 5 adet yapımızın içinde olan bilgileri konsola yazdırdık.
 
 union yani birliklerin tanımları ve kullanılması da struct’larla 
  benzerlik gösterirler. union’ların bize getirmiş olduğu en büyük kazanç aynı 
  bellek adresini değişik veri tipleri için kullanabilmemizdir.
 
 Basit bir union tanımlamak gerekirse:
 
 
 
  Birliğimizde bir tam sayı değişkeni, bir karakter değişkeni 
  ve bir de tam sayı dizisi bulunmaktadır. union deneme isimli birliğimizin boyu 
  en büyük elemanının boyu kadardır burada da 3 elemanlı tam sayı dizimiz 6 byte 
  olduğu için toplam boyut da 6 byte dır. 
    | union deneme{ int a;
 char b;
 int dizi[3];
 };
 
 
 |  
 Yapı ve birliklerin iç içe kullanımı ile ilgili bir örnek düşünürsek:
 
 
 
  Öncelikle birliğimizi inceleyecek olursak içinde kısa bir tam 
  sayı ve struct AYIR tipinden AKrktr isimli bir değişken tanımlanmış bulunuyor. 
  Yapımızda ise cIlk ve cSon adında iki karakter değişkeni barındırmaktadır. İsterseniz 
  bu tasarımımızın pratikte nasıl kullanılabileceğini düşünebiliriz.
    | struct AYIR{ char cIlk,
 cSon;
 };
 
 typedef union kisa{
 short int shSayi;
 struct AYIR AKrktr;
 }sayim;
 
 
 |  
 main() fonksiyonumuzu oluşturalım:
 
 
 
  Burada typedef ile ile belirttiğimiz kendi oluşturduğumuz türden 
  bir değişken tanımlıyoruz aynı zamanda bu birliğimizi barındırmaktadır. Ardından 
  değişken üzerinden birliğimizin elemanlarından olan shSayi adlı değişkene 19527 
  sayısını atıyoruz. 
    | int main(){ sayim saTest;
 saTest.shSayi=19527;
 printf("shSayi:%d cIlk: %c\n
 cSon:%c\n",saTest.shSayi,
 saTest.AKrktr.cIlk,
 saTest.AKrktr.cSon);
 printf("int: %d short int: %d char: %d",
 sizeof(int),sizeof(short int),sizeof(char));
 getch();
 return 0;
 }
 |  
 Çalıştırdığımızda ise çıktımız:
 
 
   
 Kısa tamsayının 2 byte, karakterin ise 1 byte yer kapladığını çıktıdan görebiliyoruz. 
  Birliklerin aynı bölgeyi kullandığını ve bu bölgeninde bizim yapımıza tekabül 
  ettiğini unutmamız lazım. Yapımızda ise kendi içindeki 1 byte lık değişkenler 
  sayesinde 19527 sayısının ilk 8 bitini cIlk ikinci 8 bitini ise cSon karşılamaktadır. 
  İlk 8 bitin karşılığı G ve ikinci 8 bitin karşılığı ise L’dir. En basit tanımıyla 
  herhangi bir karakterin bitlerini elde etmek için kullanacağımız ve bit düzeyinde 
  işlem yapacağımız silahımız bit alanlarıdır. Alt seviyeli programlamada vazgeçilmezler 
  arasında yer almaktadır düşünüyorum da sıradan bir com port’u programlamak ve 
  bir protokol meydana getirip bit bit ele alınmadada faydalı olabilir. Biz şu 
  anda temelini irdelemek için basit bir bitlere ayrıştırma programı tasarlayalım.
 
 
 
  Bir önceki verdiğimiz örnek ile yapımızın ve birliğimizin uyumu 
  aynıdır. Tek fark ise yapımızın artık sıradan bir yapı olmayıp bit alanı diye 
  isimlendirilmesidir. Basit manada : işlecinin hemen ardından o değişkene kaç 
  bit yer ayırdığımızı belirleyebiliriz. Şu anda bit alanımız 8 bitlik veriyi 
  saklayabilme kapasitesine sahiptir. Eğer birliğimizde bir 4 byte’lık tam sayı 
  tanımlamış olsaydık, ilk iki bitine ve son bitine ulaşmak bizim için önemli 
  olsaydı bit alanımızda şöyle bir oynama yapabilirdik.
    | struct bitler { int iIlkBit: 1;
 int iIknci: 1;
 int iUcncu: 1;
 int iDrdncu: 1;
 int iBsnci: 1;
 int iAltnci: 1;
 int iYednci: 1;
 int iSonBit: 1;
 };
 
 union ikili {
 char ch;
 struct bitler test;
 }ayir;
 
 
 |  Not: 4 byte 32 bittir.
 
 
 
  ‘:’ işlecinden sonra yazdığımız 29 ilk iki bitten sonraki 29 
  biti önemsememiz gerektiğini belirtmektedir.
    | struct tamsayı{ int birinci:1;
 int ikinci:1;
 :29;
 int son:1;
 };
 |  
 Son olarak örneğimize dönecek olursak bitlerine ayırmak için 
  kullanacağımız main() fonksiyonumuz şöyle olacaktır:
 
 
 
  
    | int main(void) {
 printf("Bir Karakter Giriniz\n");
 scanf("%d",&ayir.ch);
 printf("\nKarakterin Bitlerine Ayrilmis Sekli:\n");
 if(ayir.test.iSonBit)
 printf("1");
 else
 printf("0");
 if(ayir.test.iYednci)
 printf("1");
 else
 printf("0");
 if(ayir.test.iAltnci)
 printf("1");
 else
 printf("0");
 if(ayir.test.iBsnci)
 printf("1");
 else
 printf("0");
 if(ayir.test.iDrdncu)
 printf("1");
 else
 printf("0");
 if(ayir.test.iUcncu)
 printf("1");
 else
 printf("0");
 if(ayir.test.iIknci)
 printf("1");
 else
 printf("0");
 if(ayir.test.iIlkBit)
 printf("1");
 else
 printf("0");
 
 getch();
 return 0;
 }
 
 
 |  
  Gördüğünüz gibi 99 sayısının bitlerine ayrılmış 
  şekli çıktıda verilmiştir basit bir if else mantığıyla çok kolay bir şekilde 
  elde edebildik. Unutmamanız gereken bit alanları alt seviyeli programlarda gerçekten 
  çok faydalı işlere imza atmaktadır. 
 Örnek 
  uygulamayı indirmek için tıklayınız.
 
 Sorularınızı ve yorumlarınızı [email protected] adresine yollayabilirsiniz.
 Yazan: Volkan Atasever
 
 
 
                Makale:Yapılar, Birlikler ve Bit Alanları C ve Sistem Programlama Volkan Atasever
 | 
        
            |  | 
        
            |  | 
        
            | 
                    
                        
                            
                        
                            Eklenen Son 10 
                            Bu Konuda Geçmiş 10 
                        
                            Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
                         
                            Son Eklenen 10 Makale Yükleniyor
                         
                            Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
                         | 
        
            |  |