Gömülü sistemlerde projelerine başlamadan önce C programlama da özellikle struct, typedef, pointerlar konusunun özellikle benimsenmesi gerekmektedir. Bu yazıda struct, typedef ve pointer konusudan bahsedeceğiz. Ayriyetten fonksiyon göstericileri konusunu ele alacağız.
Konu boyunca gerçeklemesi yapılan kodu derlemek istediğiniz de online C compiler kullanmanız yeterli olacaktır.
1-)Typedef
İlk ele alacağımız kısım “typedef” kelimesidir. “typedef” kelimesini kullandığımızda, “struct” için yeni değişken tanımlarken struct ifadesini tekrardan kullanma ihtiyacı duymayız.Aşağıdaki iki kod bu duruma örnektir.
1 2 3 4 5 6 7 8 |
struct dogum { int gun; int ay; int yil; }; struct dogum *Ptr,sidar ; |
Yukarıda tanımlı yapımızın özelliklerine sahip değişken tanımladığımız da “struct” kelimesini kullanma ihtiyacı duyduk.
1 |
struct dogum *Ptr,sidar ; |
Ama eğer “typedef” kelimesini kullandığımız zaman böyle bir ihtiyaca gereksinim kalmayacaktır. Aşağıdaki kod bloğu buna örnektir.
1 2 3 4 5 6 7 8 |
typedef struct bilgi { int numarasi; char *isim; }ogrenci; ogrenci ogrenci_bir; |
2-)Pointerlar
Nesnellerin adres bilgilerin bellekte tutulduğu değişkenlere pointer denir.
Pointlerların kullanım amacı;
- Call by reference
- Dizileri fonksiyonlara aktarmanın tek yollu
- Bir fonksiyon birden fazla değer döndüremez. Pointerlar sayesinde birden fazla değer aktarmak mümkündür.
- Fazla yer kaplayan türler için, pointer parametre olmayan fonksiyonlara argüman geçmek maliyetli ve yavaş işlem olduğundan, pointer parametre kullanılarak maliyet ve perfonmans artışı sağlanabilir.
- Belleğe doğrudan erişim.
(*) Indirection Operant
Pointer’ın işaret ettiğine erişmek için (* ) indirection operantı kullanılır.
(&) operatörü
& operatörü, değişkenin adresini üretmek için kullanılmaktadır.
Indirection operant (*) ve & operatörü ile ilgili örnek kod örneği aşağıdaki gibidir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <stdio.h> #include <stdlib.h> int x=20; int y=10; int a=15; int *ptr; // integer cinsinden pointer tanımlandı. int main() { ptr=&x; // int cinsinden x değişkenin adresini ptr ismimli pointer göstermesini istedik. printf("x degisken %d\n",x); printf("x degiskenin bulundugu adres:%p\n",&x); printf("ptr isaret ettiği adres:%p\n",ptr); printf("ptr pointerin adresi :%p\n",&ptr); printf("ptr pointerin isaret ettigi degisken :%d\n",*ptr); // Indirection operant ile adresdeki değişkene erişildi printf("***************************************************\n"); ptr=&y; // int cinsinden y değişkeni adresini ptr ismimli pointer göstermesini istedik. printf("y degisken %d\n",y); printf("y degiskenin bulundugu adres:%p\n",&y); printf("ptr isaret ettiği adres:%p\n",ptr); printf("ptr pointerin adresi :%p\n",&ptr); printf("ptr pointerin isaret ettigi degisken :%d\n",*ptr); //indirection operant ile adresdeki değişkene erişildi. printf("***************************************************\n"); *ptr=a; // int cinsinden a değişkeni adresini ptr ismimli pointer göstermesini istedik. printf("a degiskeni %d\n",a); printf("a degiskenin bulundugu adres:%p\n",&a); printf("ptr isaret ettiği adres:%p\n",ptr); printf("ptr pointerin adresi :%p\n",&ptr); printf("ptr pointerin isaret ettigi degisken :%d\n",*ptr); //indirection operant ile adresdeki değişkene erişildi. printf("***************************************************\n"); return 0; } |
Pointer Casting
Bir pointer’ın işaret ettiğin türünü, başka türe çevireceğiz zaman casting kullanılmaktadır. Aşağıda casting işleminin yapıldığı kod örneği bulunmaktadır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <stdio.h> #include <stdlib.h> int b=71; int c=31; int* iptr; // integer cinsinden pointer tanımlandı. char* cptr; // char cinsinden pointer tanımlandı. int main() { iptr=&b; printf("iptr pointerin isaret ettigi degisken :%d\n",*iptr); //indirection operant ile adresdeki değişkene erişildi. cptr=(char*)iptr; printf("cptr pointerin isaret ettigi degisken :%d\n",*cptr); //indirection operant ile adresdeki değişkene erişildi. *cptr=(char)c; printf("cptr pointerin isaret ettigi degisken :%d\n",*cptr); //indirection operant ile adresdeki değişkene erişildi. return 0; } |
Call by Value
Lokal değişkenler, sadece tanımlanmış olduğu fonksiyonlar içerisinde geçerlidir ve bu tanımlandığı fonksiyonlarda kullanılmaktadır. Bir fonksiyon programda çağırıldığında , çağrılan fonksiyon içindeki lokal değişkenler oluşturur ve fonksiyon tamamlandığında ise bu lokal değişkenler yok yok edilir. Call by value metodu ile bunu görmekteyiz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <stdio.h> int x=5; int y=10; void degertakas (int a, int b) { int hafiza = a; a = b; b = hafiza; printf("a:%d b:%d\n", a,b); } int main () { degertakas(x,y); printf("x:%d y:%d\n", x,y); return 0; } |
Call by Reference
Fonsiyonlara değer kendisi yerine, o değerin adresi gönderilirse buna call-by-reference denir. Bu durumdan dolayı fonksiyonda yapılan değişiklik gerçek değerde değişime sebep olacaktır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <stdio.h> int x=5; int y=10; void degertakas (int *ptra, int *ptrb) { int hafiza = *ptra; *ptra = *ptrb; *ptrb = hafiza; } int main () { degertakas(&x,&y); printf("x:%d y:%d\n", x,y); return 0; } |
3-)Yapının birimlerine pointerlarla erişme
“Pointer”, “struct”ların üyesi olabilir. Aşağıdaki “struct” iki üyeden oluşmaktadır. (->) arrow operatörü ile (.) nokta operatörüyle yapı içerisindeki üyelere erişilebilir.
1 2 3 4 5 6 7 8 9 |
struct logic { int bir; int sifir; }; typedef struct logic lojik_ptr; lojik_ptr *lojik,logc ; |
Aşağıdaki kod bloğu ile yapı içerisideki üyeye değer atılmaktadır.
1 2 |
logc.bir=1; logc.sifir=0; |
4-) Struct’ların Fonksiyonlarda Kullanımı
C programlama da Struct’lar da argüman olarak kullanılabilir.Struct’ların fonksiyonlar da kullanımına ait kod blogu yukarıdaki tanımı yapılan kod blogları birlikte aşağıda verilmiştir.Fonksiyon değer döndürmeli olarak kullanılmıştır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
/****************************************************************************** Online C Compiler. Code, Compile, Run and Debug C program online. Write your code in this editor and press "Run" button to compile and execute it. *******************************************************************************/ #include <stdio.h> int state=0; typedef struct bilgi { int numarasi; char *isim; }ogrenci; ogrenci ogrenci_bir; /*****************************************************************************/ struct topla { int x; int y; }; /*****************************************************************************/ int toplam(struct topla s); /*****************************************************************************/ struct dogum { int gun; int ay; int yil; }; struct dogum *Ptr,sidar ; /*****************************************************************************/ struct logic { int bir; int sifir; }; typedef struct logic lojik_ptr; lojik_ptr *lojik,logc ; int main() { int b; struct topla s1; s1.x=1; s1.y=3; sidar.gun=2; sidar.ay=10; sidar.yil=1990; Ptr=&sidar; ogrenci_bir.isim= "sidar"; ogrenci_bir.numarasi=123; logc.bir=1; logc.sifir=0; lojik=&logc; printf("%d\n",topl(s1)); printf("%d.%d.%d\n",Ptr->gun,Ptr->ay,Ptr->yil); printf("1.numarali ogrenci numarası %d ismi %s \n",ogrenci_bir.numarasi,ogrenci_bir.isim); printf("lojik->bir değeri : %d lojik->bir adresi: %d\n",lojik->bir,&lojik->bir); printf("logc.bir değeri: %d logc.bir adresi: %d\n",logc.bir,&logc.bir); if(state==lojik->bir) { printf("lojik durum 1'dir \n"); } else { printf(" lojik durum 0'dir \n"); } return 0; } int topl(struct topla s) { return(s.x+s.y); } |
Komple kodun derlenmesi sonucu oluşan program çıktısı aşağıdaki gibidir.
5-) Fonksiyon Pointer’lar (Fonksiyon Göstericileri)
Her fonksiyonunda bir adresi bulunmaktadır. Fonksiyon Göstericileri,fonksiyonun adresini saklamak için kullanılmaktadır. Yukarıdaki örnekler de pointer’lar değişkenler (variable) adresini saklamak için kullanıldı.
Aşağıdaki örnekte int tipinde parametre alan fonksiyon göstericisi tanımlanmıştır.sonra fonksiyonun toplama ve baski fonksiyonlarının adresi &resan operatörüyle ptr ve p isimli fonksiyon göstericilerine atılmıştır.
Fonksiyon pointer gösterimi void (*pointer adı)(parametre tipi); şeklinde olur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <stdio.h> int toplama(int x,int y) { return x+y; } void baski(int arg) { printf("sonuc: %d\n",arg); } int main() { int sonuc; int (*p)(int,int); p=&toplama; sonuc=(*p)(2,3); void (*ptr)(int); ptr=&baski; ptr(sonuc); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <stdio.h> void foo (void) { printf("Merhaba\n"); } int main() { void (*fptr)(void)=&foo; printf("foo fonksiyonun adresi: %p\n",&foo); printf("fptr fonksiyon pointerinin isaret ettigi adres: %p\n",fptr); printf("foo fonksiyon pointerinin adresi: %p\n",&fptr); fptr(); return 0; } |
Call-by-Reference için kullanılan fonksiyonun, fonksiyon pointer ile çağrılması aağıdaki kod parçasındaki gibidir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <stdio.h> void takas (int *a,int *b) { int gecici=*a; *a=*b; *b=gecici; } int main() { int x=2; int y=3; void (*fptr)(int *,int *)=&takas; printf("takas fonksiyonun adresi: %p\n",&takas); printf("fptr fonksiyon pointerinin isaret ettigi adres: %p\n",fptr); printf("foo fonksiyon pointerinin adresi: %p\n",&fptr); fptr(&x,&y); printf("x nin degeri :%d y nin degeri:%d\n",x,y); return 0; } |