Makrolar, ön işlemcinin orijinal koda koyacağı kopya / yapıştırılmış metin parçalarıdır; makronun yazarı, değiştirmenin geçerli kod üretmesini umuyor.
Bunu başarmak için üç iyi "ipucu" vardır:
Makronun orijinal kod gibi davranmasına yardımcı olun
Normal kod genellikle bir noktalı virgülle sonlandırılır. Kullanıcı kodu gerek duymazsa görüntüleyebilir ...
doSomething(1) ;
DO_SOMETHING_ELSE(2) // <== Hey? What's this?
doSomethingElseAgain(3) ;
Bu, kullanıcının, noktalı virgül yoksa derleyiciden hata üretmesini beklediği anlamına gelir.
Ancak asıl gerçek neden, bir zamanlar, makronun yazarının makroyu belki de gerçek bir işlevle (belki de satır içi) değiştirmesi gerekeceğidir. Yani makro gerçekten bir gibi davranmalıdır.
Bu yüzden, yarı-kolon gerektiren bir makroya sahip olmalıyız.
Geçerli bir kod üret
Jfm3'ün cevabında gösterildiği gibi, bazen makro birden fazla talimat içerir. Makro bir if ifadesinin içinde kullanılıyorsa, bu sorunlu olacaktır:
if(bIsOk)
MY_MACRO(42) ;
Bu makro şu şekilde genişletilebilir:
#define MY_MACRO(x) f(x) ; g(x)
if(bIsOk)
f(42) ; g(42) ; // was MY_MACRO(42) ;
g
Fonksiyon bakılmaksızın değerinin çalıştırılacaktır bIsOk
.
Bu, makroya bir kapsam eklememiz gerektiği anlamına gelir:
#define MY_MACRO(x) { f(x) ; g(x) ; }
if(bIsOk)
{ f(42) ; g(42) ; } ; // was MY_MACRO(42) ;
Geçerli bir kod üret 2
Makro şuna benzerse:
#define MY_MACRO(x) int i = x + 1 ; f(i) ;
Aşağıdaki kodda başka bir sorunla karşılaşabiliriz:
void doSomething()
{
int i = 25 ;
MY_MACRO(32) ;
}
Çünkü şu şekilde genişleyecektir:
void doSomething()
{
int i = 25 ;
int i = 32 + 1 ; f(i) ; ; // was MY_MACRO(32) ;
}
Bu kod elbette derlenmeyecek. Yani, yine, çözüm bir kapsam kullanıyor:
#define MY_MACRO(x) { int i = x + 1 ; f(i) ; }
void doSomething()
{
int i = 25 ;
{ int i = 32 + 1 ; f(i) ; } ; // was MY_MACRO(32) ;
}
Kod tekrar doğru şekilde çalışır.
Noktalı kolon + kapsam efektlerini birleştirmek?
Bu efekti üreten bir C / C ++ deyimi vardır: do / while döngüsü:
do
{
// code
}
while(false) ;
Do / while, bir kapsam oluşturabilir, böylece makronun kodunu kapsülleyebilir ve sonunda bir yarım kolon gerektirir, böylece bir kod gerektiren kod haline gelir.
Bonus?
C ++ derleyicisi do / while döngüsünü optimize eder, çünkü post-koşulunun yanlış olması derleme zamanında bilinir. Bu, aşağıdaki gibi bir makro anlamına gelir:
#define MY_MACRO(x) \
do \
{ \
const int i = x + 1 ; \
f(i) ; g(i) ; \
} \
while(false)
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
MY_MACRO(42) ;
// Etc.
}
doğru şekilde genişleyecek
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
do
{
const int i = 42 + 1 ; // was MY_MACRO(42) ;
f(i) ; g(i) ;
}
while(false) ;
// Etc.
}
ve sonra derlenir ve
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
{
f(43) ; g(43) ;
}
// Etc.
}
void
için, sonuna türünde bir ifade eklerdim ... like ((void) 0) .