C'De Makrolar!

Trayhoper

New member
Katılım
30 Mar 2006
Mesajlar
26
Reaction score
0
Puanları
0
Öncelikle makrolar hakkında bilgi vereyim.



Çoğunuz programlarınızda #define ifadesini kullanmışsınızdır. Bu ifade sembolik sabit (symbolic constant) tanımlarında kullanılır. Makrolarda buna benzer fakat makrolar genişletilebilir. Ve birden fazla değer alabilir. Fonksiyon gibi prototiplenip fonksiyonların yerini alabilirler. Makrolarda tip denetimi yapılmaz. Ve yanlış tip yüklediğinizde derleyici tarafından uyarılmazsınız.



Makronun tanımı şu şekildedir. Makrolar sembolik sabit gibi tanımlanırlar ve bundan farklı olarak birden fazla değer alabilir ve fonksiyon yerine geçebilirler.



Misal






#define PI 3.1415 //bu bir sembolik sabittit

#define MESAJ printf(“Merhaba Hasan” ) // bu bir makrodur



Bir noktaya dikkatinizi çekmek istiyorum eğer makro sonuna ; (noktalı virgül ) koymazsanız program içinde kullanırken siz makronun yanına ; koymalısınız. Misal






#define MESAJ printf(“Merhaba Hasan")

void main(void)

{

MESAJ; //nokatlı virgül kullandım

}





#define MESAJ printf(“Merhaba Hasan); // burada noktalı virgül kullandım

void main(void)

{

MESAJ //burada kullanmama gerek yok

}



gördüğünüz gibi çıktı fonksiyonunu makro olarak tanımladık. Bu sadece bir tür kullanımı istersek bunu fonksiyon gibi değer alabilen halde kullanabiliriz. Bu da makroların parametre alması ile ilgilidir.



C ve C++ da makrolara parametre ataması yapabilirsiniz. Buna bir örnek verelim






#include “stdio.h”

#include “conio.h”





#define TOPLA(x,y) (x+y)





int main()

{

printf(“%d”,TOPLA(5,3));

return 0;

}



bu kullanım iki sayının toplamını makro kullarak yapıyor. Makrolarda kesinlikle tip tanımı yapılmaz. Ve size uyarıda bulunulmaz. Makrolara yükleme yaparken deneyimsiz programcılar çok çabul hataya düşerler. Makro genişlemöesi olayı birden fazla ara değişkenin makroya yüklenmesidir. Fakat aşırı genişleme programınızın kırlımasına neden olur. Misal






#define OKU(s) scanf(“%d”,&s)

int main()

{

int sayi;

OKU(sayi); // makro genişliyor

}



makro tanımı dikkat isteyen bir iştir. Bir boşluğun veya parantezin çok büyük önemi vardır. Şimdi bunları görelim.



Birincisi parantezin önemi



Parantezin önemi işlem önceliği için gereklidir. Paranteze alınmayan makrolar işlem önceliğini derleyicinin insiyatifine bırakır. Bir x (3*x) makrosunu



#define ISLEM(x) x * 3 * x yazarsanız istediğiniz sonucu alamazsınız. Veya kare alma işlemi yapan bir makroya x*x deyip sonra buna (x+5) dediğinizde istediğiniz sonucu alamazsınız. İşlem önceliği için tüm makro gövdesini paranteze almalısınız.



Misal



#define ISLEM(x) ((x) * (3 *x))

şeklinde bir kullanım yapmanız gerekir.



Bir diğer problem makronun boşluk karaterine duyarlı olmasıdır. Örnek



#define ISLEM (x) ((x)*(x))

derleyici tarafından algılanma şekli



(x) ((x)*(x)) dir ayni argüman bu makro için yoktur denir.



Nedeni (x) in mako sabit ismi ile bitişik yazılmamasından kaynaklanır



#define ISLEM(x) ((x)*(x)) bu sorunu çözer. Bu duyarlılığın sebebi sabit tanımlarından gelir. Sabit tanımında iki değer vardır. Yerine yazılacak isim ve o yazılan ile değşecek esas değer. Ve bunlar da boşluk katarı ile ifade edilir.



Bu kadar bilgiden sonra bir örnek uygulama yazalım ve açıklayalım.






#include "stdio.h"

#include "conio.h"

#define YENISATIR "n"

#define YAZIYAZ(yazi) printf("%s",yazi)

#define DEGERYAZ(d) printf("%d",d)

#define DEGEROKU(deger) scanf("%d",(&deger))

#define KARE(x) ((x)*(x))

#define TUSBEKLE getch()

#define TAMSAYI(deg) int deg

void main()

{

TAMSAYI(isayi);

YAZIYAZ("Lutfen karesini almak istediginiz sayiyi girin: ");

DEGEROKU(isayi);

YAZIYAZ("Bu sayinin karesi: ");

DEGERYAZ(KARE(isayi)); YAZIYAZ(YENISATIR);

YAZIYAZ("CODED BY K@OS");

YAZIYAZ(YENISATIR);

YAZIYAZ("Cyber-Warrior");

TUSBEKLE;

}



evet önce standart makroları tanımladık. Ve main içinde hiç C++ syntaxı kullanmadan bir kod yazdık. Böyle yaparak kendi syntaxınızı bile oluşturabilirsiniz. Misal bir header içine bu makroları yazıp. Normal program yazarken kendi syntaxınız ile bir kodlama sistemi geliştirebilirsiniz. Yukarıda örneğini verdiğim kodda aynen öyle değişken tanımını bile kendi makromuz sayesinde yaptık.



Şimdi size derleyici üstünde tanımlı beş adet makroyu göstereceğim. Bu makrolar derleyici için özel anlam taşır ve iki alt çizgi ile başlar ve biterler.



__LINE__ : Bu makro kaynak kodunun o anki satır numarasını taşıyan bir sabittir. Sayısal değeri 10luk sistemdedir.



__FILE__ : Kaynak dosyasının adını tutan makrodur



__DATE__ : Tarihi tutan makrodur



__TIMESTAMP__ : Kaynak kod dosyası üzerinde yapılan en son değişikliğin tarih ve saatini tutar



__STDC__ : Kodun Ansi C standartında uyumlu olup olmadığını bildirir.





Misal

printf("Kaynak dosya adi: %snSaat ve Tarih: %snSatir No: %d",__FILE__,__DATE__,__LINE__);



Kodunu derlediğinizde aşağıakine benzer bir çıktı alırsınız



Kaynak dosya adi: .prog.cpp

Saat ve Tarih: Apr 5 2006

Satir No: 10



Bunuda bitirdikten sonra sıra geldi önişlemci ifadelerine.



Önişlemci kodları derleyicinin kodu tamamen çevirmeden önce derlenen kısımlarıdır. Ana koddan en önce önişlemciler çalışır. Misal #include ifadesi. Siz bir header dosyası içinde bir fonksiyonu kullanacağınız zaman #include dersiniz. Derleyici önce #include ifadesine bakar ve karşısındaki header dosyasına ulaşır önce içindeki fonksiyonları compile eder ve ana programda kullanılan fonksiyon çağrılarının doğru bir biçimde çaışmasını sağlar. İşte bu gibi öncelikli durumlarda önişlemci ifadeleri yardıma gelir. C++ da



#define, #include, #else, #elif, #endif, #error, #if, #ifdef,#ifndef,#import,#line,#pragma,#undef,#using olmak üzere 14 tane önişlemci anahtarı vardır. Bunlardan #include ve #define ye aşinasınız o yüzden onları anlatmayacağım. Ve bu bölümde anlatacağım önişlemciler.



#ifdef ,#endif, #else



#undef



Çünkü makale epey uzadı. Kalan önişlemcileri de ikinci makaleye eklicem. Şimdi devam edelim.



#ifdef , #else ve #endif önişlemcileri



Bu önişlemciler programa koşullu ekleme yapılmasını sağlar. Misal



#include "stdio.h"

#include "conio.h"

#define PI 3.1415



#ifdef PI

#define OK 0

#else

#define PI 3.1415

#define OK 1

#endif













void main()

{

if (OK == 0)

printf("PI Sayisi Tanimli");

else

printf("PI Sayisi Tanimli Degil. Simdi Tanimlandi..");

getch();

}





Önce programı #define PI olarak çalıştırın ve sonucu görün. Daha sonra #define PI satırını koddan çıkarın ve çalıştırın. Ve sonucu gözlemleyin. Eğer PI sayısı tanımlanmış ise bize pi sayısının tanımlandığını söylüyor. Değilse tanımlanmadığını söylüyor ve şimdi tanımlandığını söylüyor. Bu bize bir sabitin önceden olup olmadığını bulmamıza yarar. Eğer derleyiciye ait bir sabit kullanmaktan şüpheleniyorsak bunu önceden bakıp bulabiliriz. Misal SW_SHOWNORMAL mesajı önceden derleyicide bulunan bir sabittir.



Biz bunu #ifdef ile kontrol edebiliriz.



#ifdef SW_SHOWNORMAL

#define Hasan_SHOWNORMAL 1

#endif





Sıradaki önişlemci #undef



#undef, #define ile sabitlenmiş bir sabiti kaldırır. Misal



#ifdef SW_SHOWNORMAL

#undef SW_SHOWNORMAL

#define SW_SHOWNORMAL 2

#endif

Alıntıdır..
 
Geri
Üst