■この記事の概要
この記事では、C言語のプリプロセッサディレクティブ#ifdef
と#if
の違いを解説しています。#ifdef
はマクロが定義済みかどうかを確認し、#if
は評価式が非ゼロかどうかを確認します。コード例を交えて推奨される使い方やエラー防止策も詳述されています。
■#ifdefは定義済みなら成立
#include <stdio.h>
int main(void){
//DEBUG未定義
#ifdef DEBUG
puts("来ない");
#endif
//gcc -DDEBUG=0相当
#define DEBUG 0
#ifdef DEBUG //定義済み
printf("%d:来る\n",__LINE__);
#endif
//gcc -DDEBUG 相当
#undef DEBUG //定義取り消し
#define DEBUG 1
#ifdef DEBUG //定義済み
printf("%d:来る\n",__LINE__);
#endif
}
#ifdef DEBUG
DEBUGマクロが
定義済みなら成立し
未定義なら成立しません。
DEBUGの値がゼロか非ゼロかは
関係ありません。
■#ifは非ゼロなら成立
#include <stdio.h>
int main(void){
//DEBUG未定義
#if DEBUG
puts("来ない");
#endif
//gcc -DDEBUG=0相当
#define DEBUG 0
#if DEBUG //ゼロ
puts("来ない");
#endif
//gcc -DDEBUG 相当
#undef DEBUG //定義取り消し
#define DEBUG 1
#if DEBUG //非ゼロ
printf("%d:来る\n",__LINE__);
#endif
//gcc -DDEBUG=2相当
#undef DEBUG //定義取り消し
#define DEBUG 2
#if DEBUG <= 1 //偽=ゼロ
puts("来ない");
#endif
#if DEBUG <= 2 //真=非ゼロ
printf("%d:来る\n",__LINE__);
#endif
}
#if DEBUG
DEBUG式が
非ゼロなら成立し
ゼロなら成立しません。
DEBUGの所に
if DEBUG <= 2 のような
式を書く事ができます。
デバッグレベルに応じて
展開を制御する時によく使います。
■#ifと#endifしか使っていない例(非推奨)
char *cpu[]={
"z80",
#if CPU==3
"Core i3"
#endif
#if CPU==5
"Core i5"
#endif
#if CPU==7
"Core i7"
#endif
#if CPU==9
"Core i9"
#endif
};
#include <stdio.h>
int main(void){
printf("%s\n",cpu[1]);//cpu[1]が展開されない場合暴走するかも
}
gcc -DCPU=9等とコンパイル時に適切な引数が与えられた時は問題がありませんが
gcc -DCPU=1234等と指定された場合コンパイルエラーにならず、
プログラム実行時異常終了してしまう可能性があります。
■#elifと#errorを使った例(推奨)
char *cpu[]={
"Z80",
#if CPU==3
"Core i3"
#elif CPU==5
"Core i5"
#elif CPU==7
"Core i7"
#elif CPU==9
"Core i9"
#else
#error "★未知のCPUはここでコンパイルエラーになる"
#endif
};
#include <stdio.h>
int main(void){
printf("%s\n",cpu[1]);
}
#elifと#errorを組み合わせると
予期せぬコンパイル状態となると
コンパイルエラーになってくれるので
間違いに直ぐ気が付きます。