Sunday, January 14, 2007

Struct ve Union da ne ola ki...

Neredeyse yazdığım programların hiç birinde union kullanmadım, hatta bu cümleyi okurken bazılarımız union da ne ola ki diyebilir.
struct C de yaygin olarak kullanilan, C++ da ise class olarak bilinen bir veri tipidir. C++ da ki class ile C de ki struct in farklari tabi ki vardır, orneğin default olarak class yapısında değişkenler private tanımlanır. yani;

class emreknlkCokClass{ //:))
int var;
};

emreknlkCokClass sınıfının içerisinde tanımlanmış var değişkeni private dır ve dışarıdan erişelemez. struct da ise varsayılan erişim tipi public olup dışardan değişkenlere erişilebilir.

Neyse benim bu akşam canım sıkıldı. O yüzden struct ve union ı kendime oyuncak seçtim, hadi biraz oynayalım ;)

1) Makineniz little endian mı big endian mı öğrenmek istermisiniz...

Little endian ve big endian kavramları nedir bilmeyenler için özetleyim: Verilerinizin bellekte nasıl saklandığına yönelik kavramlardır. Big endian kısmında verinin en yüksek anlamlı kısmı düşük adreste, düşük anlamlı kısmı yüksek adreste saklanır. Bu insanların da rahatça anlayabileceği bir yöntemdir. Mesala $4579 verisini 1000 no lu bellek gözüne yazmak isterseniz, 1000 nolu bellek gözünün içeriği 45 , 1001 no lu bellek gözünün içeriği 79 olacaktır.
Little endian da tahmin edeceğiniz üzere bunun tam tersi, 1000 nolu bellek gözünde 79, 1001 nolu bellek gözünde 45 yazacak...

işte union yapısı ile:
#include<stdio.h>

union WhichEndian{
int number; //4 byte
char byte; //1 byte
};


int main(){

union WhichEndian find;
int i;
char* ptr;

find.number = 0x12345678;

ptr = &find.byte;

for(i = 0; i < sizeof( int ) ; i++)
printf("Memory address: %p\tData: %x\n",ptr, (int)*(ptr++));

return 0;
}


ve benim makinemde işte size ekran çıktısı:

Memory address: 0012FF7C Data: 78
Memory address: 0012FF7D Data: 56
Memory address: 0012FF7E Data: 34
Memory address: 0012FF7F Data: 12
Press any key to continue


Gördüğünüz gibi little endian çıktı benim toşibam :))

Gelelim kodaa, union ne yapar, ne işe yarar kısaca bir özet geçeyim: union içerisinde ki bütün değişkenleri bellekte aynı offset değerinden başlayarak yerleştirir. Kodda bir integer ve bir char kullandık, bunların ikisininde başlangıç adresleri aynıdır. aslında bu kodda char byte değişkenine gerek yoktu, aslında yukardaki sonucu elde etmek için union kullanmak bile gereksizdi, ama burada dikkatinizi çekmek istediğim nokta:

ptr = &find.byte;

satırıdır. Burada ptr adresi byte değişkenin adresini içeriyorsa da aslında number değişkeni ile byte değişkeni aynı bellek gözünden başlayarak tanımlandıkları için, for döngüsü içerisinde number değişkeninin içeriğini sıra ile düzgün bastırabildik.

Eğer burada union değil de struct kullanacak olsaydık bu kod çalışmayacaktı. Çünkü byte değişkeni number ın bittiği yerden başlayacaktı...



2) Struct ile bit show

Diyelim ki elimiz de 8 tane led var. Bu ledlerin durumunu ( on/off ) kontrol etmek istiyoruz. Her bir led için 1 integer değer tutarsak 8*sizeof(int) kadar bellek bosuna gitmis olacak. Ben diyorum ki gelin her led için 1 bit kullanalım ve toplam 1 byte yer ayırarak bu işi bitirelim...

işte gerekli struct yapısı ve program kodu

#include<stdio.h>

#define OFF 0
#define ON 1

struct LedControl
{
unsigned char led1: 1;
unsigned char led2: 1;
unsigned char led3: 1;
unsigned char led4: 1;
unsigned char led5: 1;
unsigned char led6: 1;
unsigned char led7: 1;
unsigned char led8: 1;

};

int main(){

struct LedControl vecii; //LED leri vecii yaksin kapasin...

printf("Led Control %d byte yer kaplar..\n",sizeof(vecii));

vecii.led1 = OFF;

printf("1. led: %d\n",vecii.led1);

vecii.led1 = ON;

printf("1. led: %d\n",vecii.led1);

return 0;
}

Görüldüğü gibi struct içinde tanımlana led lerin her biri 1 bit yer kaplar. Bu bitlere erişim normal değişkenlere erişim gibidir. her değişken için bir bit ayırmak zorunluluğu yoktur.

Şimdi ekran çıktısını inceleyip struct için gerçekten 1 byte yer ayrıldığını görebiliriz:

Led Control 1 byte yer kaplar..
1. led: 0
1. led: 1
Press any key to continue


Peki nerelerde kullanılır bu yapı, herhalde enterprise edition lı program yazarken pek işimiz düşmez bu yapılara:) Ama sistem programlama da, driver yazmada , embeded sistemler için yazılım geliştirme de ciddi derece başvurulabilen bir metot olarak karşımıza çıkar.

Bu yazımda da size basitçe struct ve union ı tekrar hatırlatmak istedim. Basit şeyler olmasına karşın pek başvurulmadığı için zamanla fonksyonları unutulabiliyor. Diğer yazılarımda görüşmek üzere...

No comments: