スポンサーリンク

対策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;
}

スポンサーリンク