10 Ocak 2014 Cuma

C 'de Belleklerle İşlemler

    Merhaba arkadaşlar bugünkü konumuzda C 'de türden bağımsız işlemler (kopyalama vs.) yapacağız. Öncelikle jenerik programlama(Generic Programming) nedir bir ona el atalım. Jenerik programlama türden bağımsız programlamadır. Java, C++ gibi diller bunlara direk destek verirken biz yine C 'de kendi çabalarımız ile birşeyler yapmaya çalışacağız. Bunu yaparken bazı standart fonksiyonlardan yararlanacağız bunlar ; memset, memcpy, memmove, memchr, memcmp bunları birazdan prototipleri ile birlikte açıklayacağım.

    Bu tarz bir programlama ne işimize yarar öncelikle ona bakalım. Bu tarz programlamadaki en büyük avantajlardan biri en basitinden bir fonksiyonu türe bağlı olmadan yazabilmektir. Örneğin standart qsort fonksiyonu türden bağımsız bir fonksiyondur ve ne türden dizi gönderirseniz onu sıralar. Böylece onca kodu tekrardan yazma zahmetinden kurtulmuş oluruz.

    Kısaca void *
    C 'de jenerik fonksiyon yazabilmemiz için öncelikle bilmemiz gerek bir tür var bunun adı void * türü. Jenerik bir fonksiyon yazmamız için parametremiz de belirli bir tür almamalıyız bunun çözümü ise void * 'dır.
void * her türden nesneyi tutabilen pointerdır. Fakat içeriğini, almak amacıyla kullanılamaz. Kullanılırken de istenilen türe cast edilmesi C++ 'da mecburi iken C 'de değildir fakat edilmelidir.

    Bellek bloklarında işlem yapan fonksiyonlar
    void aldığımız parametrelerin ne tür olduğunu bilmediğimizden bunlara atama vb. işlemler yaparken bellek bloklarını kullanmalıyız. Bunun için <string.h> 'da bildirilmiş fonksiyonlarımız var bunlar;

Memset
void * memset ( void * ptr, int value, size_t num );


Bu fonksiyon atama işlemleri için kullanılır. İlk parametresi atanacak adresi alır, ikincisi atanacak değeri, üçüncüsü ise kaç baytını value ile atamak istediğini belirtir. Gönderilen adres ile geri döner.

Ör:  
char str[] = "Guven";

memset(str, 'c', 3);
puts(str);

Çıktı -> cccen  olur.

Memcpy-Memmove
void * memcpy ( void * destination, const void * source, size_t num );


Bu fonksiyon bellek kopyalaması yapar. Kopyalama mantığı şu şekildedir birlikte memcpy yazalım nasıl olduğunu anlamış oluruz.

void * mymemcpy ( void * pDest, const void * pSource, size_t num)
{




    char *pd = (char *)pDest;

    const char *ps = (const char *)pSource;



    while (num--)

         *pd++ = *ps++;



    return pDest;

}

İşte size kendi yazdığımız basitçe memcpy fonksiyonumuz. Blok blok kopyalama yapar. Eğer bloklar çakışık ise memmove kullanmanızı öneririm.

void * memmove ( void * destination, const void * source, size_t num );

Protoip aynıdır işleme mantığıda benzerdir blokları kopyalar.

Memchr


void *memchr(const void *str, int c, size_t n);

Prototipine sahip fonksiyonumuz ilk parametresinde gönderdiğimiz nesnenin içinde ikinci parametrede gönderdiğimiz (Unsigned char) c karakterini arar. Bulduğu yerin adresini döner.

Kullanımı şu şekildedir.

const str[] = "Guven";
const char ch = 'u';
char *ptr;

ptr = (char *)memchr(str, ch, strlen(str));

// ptr burada str + 1 adresini tutmuş olur.

Memcmp

int memcmp(const void *str1, const void *str2, size_t n)

Protoripine sahip memcmp fonksiyonu karşılaştırma işlemini yapar. Eğer birinci büyükse pozitif ikinci büyükse negatif eşit iseler 0 değeri ile geri döner. Birinci ve ikinci parametre karşılaştırılacak nesneler üçüncü parametre ise kaç baytın karşılaştırılacağını ifade eder.

Bu fonksiyon ile karşılaştırılma yapılırken bayt bayt karşılaştırıldığını göz önüne alarak fonksiyonu kullanınız!

Bugünde yazımızın sonuna geldik arkadaşlar umarım faydalı olmuştur. Yazılarımı arada tekrar okuyarak eksikleri ve hataları güncellemekteyim hata veya eksik bulduğunuz kısımları bana iletebilirsiniz. Teşekkürler.


Hiç yorum yok:

Yorum Gönder