Macro adalah copy / paste teks yang akan dimasukkan oleh pre-processor ke dalam kode asli; penulis makro berharap penggantian akan menghasilkan kode yang valid.
Ada tiga "tips" yang baik untuk berhasil dalam hal itu:
Bantu makro berperilaku seperti kode asli
Kode normal biasanya diakhiri dengan titik koma. Haruskah kode tampilan pengguna tidak memerlukan satu ...
doSomething(1) ;
DO_SOMETHING_ELSE(2) // <== Hey? What's this?
doSomethingElseAgain(3) ;
Ini berarti pengguna mengharapkan kompiler untuk menghasilkan kesalahan jika titik koma tidak ada.
Tetapi alasan sebenarnya yang sangat bagus adalah bahwa pada suatu saat, penulis makro mungkin perlu mengganti makro dengan fungsi asli (mungkin diuraikan). Jadi makro harus benar - benar berperilaku seperti itu.
Jadi kita harus memiliki makro yang membutuhkan semi-colon.
Menghasilkan kode yang valid
Seperti yang ditunjukkan pada jawaban jfm3, terkadang makro berisi lebih dari satu instruksi. Dan jika makro digunakan di dalam pernyataan if, ini akan bermasalah:
if(bIsOk)
MY_MACRO(42) ;
Makro ini dapat diperluas sebagai:
#define MY_MACRO(x) f(x) ; g(x)
if(bIsOk)
f(42) ; g(42) ; // was MY_MACRO(42) ;
The g
fungsi akan dieksekusi terlepas dari nilai bIsOk
.
Ini berarti bahwa kita harus menambahkan ruang lingkup ke makro:
#define MY_MACRO(x) { f(x) ; g(x) ; }
if(bIsOk)
{ f(42) ; g(42) ; } ; // was MY_MACRO(42) ;
Menghasilkan kode yang valid 2
Jika makro adalah sesuatu seperti:
#define MY_MACRO(x) int i = x + 1 ; f(i) ;
Kami dapat memiliki masalah lain dalam kode berikut:
void doSomething()
{
int i = 25 ;
MY_MACRO(32) ;
}
Karena itu akan berkembang sebagai:
void doSomething()
{
int i = 25 ;
int i = 32 + 1 ; f(i) ; ; // was MY_MACRO(32) ;
}
Kode ini tidak akan dikompilasi, tentu saja. Jadi, sekali lagi, solusinya menggunakan cakupan:
#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) ;
}
Kode berperilaku dengan benar lagi.
Menggabungkan efek semi-colon + scope?
Ada satu idiom C / C ++ yang menghasilkan efek ini: Loop do / while:
do
{
// code
}
while(false) ;
Do / while dapat membuat ruang lingkup, dengan demikian merangkum kode makro, dan membutuhkan semi-colon pada akhirnya, sehingga berkembang menjadi kode yang membutuhkannya.
Bonusnya?
Compiler C ++ akan mengoptimalkan loop do / while, karena post-conditionnya salah diketahui pada waktu kompilasi. Ini berarti makro seperti:
#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.
}
akan berkembang dengan benar sebagai
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.
}
dan kemudian dikompilasi dan dioptimalkan sebagai
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
{
f(43) ; g(43) ;
}
// Etc.
}
void
tipe di akhir ... like ((void) 0) .