スポンサーリンク
対策1 if文の中にマクロを使うときは{}を使う
複数行のマクロをif文の中で使うときは、if文で{}を使うと安全度が増します。
例えば、下記のソースコードがあったとします。
$ cat sample.c #include <stdio.h> #define SUCCESS 1 #define FALSE 0 #define TEST_PRINT(...) printf(__VA_ARGS__) #define TEST_PRINT_ERROR(status) if((status)){\ printf("OK\n");\ }else{\ printf("NG\n");\ } int main(){ #if 0 //コンパイルNG if(SUCCESS) TEST_PRINT_ERROR(1); else TEST_PRINT("NG\n"); #endif #if 1 //コンパイルOK if(SUCCESS){ TEST_PRINT_ERROR(1); }else{ TEST_PRINT("NG\n"); } #endif return 0; }
下記の部分はコンパイルエラーとなります。
//コンパイルNG if(SUCCESS) TEST_PRINT_ERROR(1); else TEST_PRINT("NG\n");
下記が実際のエラーです。
$ gcc -o sample sample.c sample.c:18:3: warning: add explicit braces to avoid dangling else [-Wdangling-else] TEST_PRINT_ERROR(1); ^ sample.c:9:14: note: expanded from macro 'TEST_PRINT_ERROR' }else{\ ^ sample.c:19:2: error: expected expression else ^ 1 warning and 1 error generated.
if文で{}を使うとコンパイルが通ります。
//コンパイルOK if(SUCCESS){ TEST_PRINT_ERROR(1); }else{ TEST_PRINT("NG\n"); }
スポンサーリンク
対策2 マクロをdo{}while(0)で囲む
マクロをdo{}while(0)で囲むと、先程の{}がないif文でもコンパイルが通ります。
こちらの方がより安全ですね。
先程のマクロをdo{}while(0)で囲みます。
コンパイルが通りますね。
ただ、そもそも、if文では{}をつけるのが良いとは思いますね。
$ cat sample2.c #include <stdio.h> #define SUCCESS 1 #define FALSE 0 #define TEST_PRINT(...) printf(__VA_ARGS__) #define TEST_PRINT_ERROR(status) do{if((status)){\ printf("OK\n");\ }else{\ printf("NG\n");\ }\ }while(0) int main(){ if(SUCCESS) TEST_PRINT_ERROR(1); else TEST_PRINT("NG\n"); return 0; }
スポンサーリンク