C MACRO Notları
Macro'nun Tanımlı Olmasını Zorlamak
Örnek:
#if !defined MYMACRO
#error "MYMACRO is not defined"
#endif
Sayı Sabitleri için Macrolar
Parantez içinde yazılması daha sağlıklı
#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)
Fonksiyon Gibi Macrolar - Function Like Macros
C ile reflection yapmak mümkün değil ancak MACRO kullanarak bazı
metodların işleyişini değiştirebilmek mümkün. Bu tür macrolara "function
like macros" deniliyor.
Örneğin bir fonksiyonu tanımsız hale getirebiliriz. Özellikle log'lama
yeteneğini debug/release derlemeye göre değiştirebilmek için çok
kullanışlı bir örnek aşağıda.
#ifdef LOG_ENABLED
extern "C" void LOG_DEBUG (const char* data);
#else
#define LOG_DEBUG(data); //Parantez ve macro arasında boşluk olmamalı
#endif
Bir başka yöntem ise boşa tanımlama. Örneğin assert macrosu Visual C++'ta aşağıdaki gibi tanımlı, dolayısıyla sadece debug derlemede çalışır.
#ifdef NDEBUG
#define assert (_expression) ((void)0)
#endif
Macrolarda Yan Etkilere Dikkat Etmek
Macroları çağırırken, yan etkilere dikkat etmek gerekir. Örnekte aynı işi yapan iki farklı macro tanımlanmış.
Eğer bu macro max(i++,--j) şeklinde çağırılırsa, ilk macroda her a ve b tanımlaması için, istenenden daha fazla işleme sebep olur.
Macroların Parse Edilmesi
Macrolar preprocessor tarafından parse edilirler. Eğer macroya geçilen parametrede virgül karakteri varsa, birden fazla parametre geçiliyormuş gibi algılanabilir. Örnek'te template kullanıldığı için virgül hataya sebep oluyor.
TRAP_EXCEPTION
(
(std::map<MyType, bool> Map;)
)
Bu gibi durumlarda macro içinde __VA_ARGS__ kullanılabilir.#define TRAP_EXCEPTION(...) \
try \
{ \
try{ __VA_ARGS__ } \
catch(Engine::Exception& e) \
{ \
throw MyException(e.message()); \
} \
}
Stringification - String Haline Getirmek
Bu tür macrolarda ise macro'ya verilen parametre # işareti ile string
haline getiriliyor. Bu yöntemin reflection'da nasıl kullanıldığını
açıklamam lazım. Örnek:
Stringification ve Birleştirme
Parametreler #ile string haline getirilir, daha sonra birleştirme için kullanılan karakter string şeklinde araya yazılır.
#define space_conc(str1,str2) #str1 " " #str2
space_conc(hello, world)
) şeklinde çağırıldığında macro "hello" " " "world"
şeklinde açılır. Derleyici stringleri birleştirerek
"hello world"
haline getirir.
Concatinaion - String haline getirmeden, sadece sembol olarak birleştirme
Bu tür macrolarda ise macro açıldıktan sonra ## işaretinin her iki
yanındaki karakterler birleştirilir. Bu yöntemin reflection'da nasıl
kullanıldığını açıklamam lazım. Örnek:
struct command
{char *name;
void (*function) (void);
};
struct command commands[] =
{
{ "quit", quit_command },
{ "help", help_command },
...
};
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};
Hiç yorum yok:
Yorum Gönder