本トピックは発展的な内容を扱うので飛ばして構いません。一通りC言語の学習を終えてから見ることをお勧めします。
マクロの定義によって処理を変える
#ifdef #ifndef #else #endif
これらのプリプロセッサ命令を使用するとマクロが定義されているかどうかによって処理を分けることができます。
#ifdef マクロ名
//マクロが定義されているときの処理
#endif
マクロ名が定義されている時のみ、#ifdefから#endifまでの処理を実行します。
#ifdef マクロ名
//マクロが定義されているときの処理
#else
//マクロが定義されていないときの処理
#endif
#elseをつかうと、マクロが定義されていないときの処理も書くことができます。条件式が満たされない場合はそこの処理はコンパイラに無視されます。つまりその部分は文法が間違えていてもコンパイルは通ります。
#include <stdio.h>
#define MACRO
int seki(int a,int b) {return a*b;}
int main(void){
#ifdef MACRO
puts("MACRO:defined");
#else
puts("MACRO:undefined");
#endif
return 0;
}
実行結果
MACRO:defined
マクロが定義されているのでMACRO:definedと出力されます。
#include <stdio.h>
#define macro
int seki(int a,int b) {return a*b;}
int main(void){
#ifdef MACRO
puts("MACRO:defined");
#else
puts("MACRO:undefined");
#endif
return 0;
}
実行結果
MACRO:undefined
C言語では文字小文字を区別します。マクロ名も大文字小文字を区別するので、大文字のMACROは定義されていませんよってMACRO:undefinedと表示されます。
#ifを使用すると、マクロの値によって処理を変えることができます。#ifdefは定義されているかによって処理を変えるのに対し、#ifは値によって条件分岐します。#elseifは、#elseと#ifを合わせた命令で、#ifを入れ子にした指令です。
#include <stdio.h>
#define FLAG 1
#define NUM 3
int main(void){
#if FLAG
puts("FLAG!=0");
#else
puts("FLAG==0");
#endif
#if NUM==2
puts("NUM=2");
#elif NUM==1
puts("NUM==1");
#else
puts("NUM!=1,NUM!=2");
#endif
return 0;
}
実行結果
FLAG!=0
NUM!=1,NUM!=2
マクロを変数に書き換え、if文を使って書き換えると次のようになります。
#include <stdio.h>
int main(void){
int FLAG=3;
int NUM=3;
if (FLAG)
puts("FLAG!=0");
else
puts("FLAG==0");
if (NUM==2)
puts("NUM=2");
else if (NUM==1)
puts("NUM==1");
else
puts("NUM!=1,NUM!=2");
return 0;
}
実行結果
FLAG!=0
NUM!=1,NUM!=2
これらのプリプロセッサ命令は同じヘッダーファイルを何重にもインクルードされてしまうことを防ぐ(インクルードガード)際に使用します。また例えばWindows APIではUnicodeに対応しているかどうかや、64ビットか32ビットによって処理を変える際にも使用されています。
コンパイラに関する指令
コンパイラに対して特別なコンパイル条件を与えるには、#pragmaを使用します。
#pragma指令は、処理系によって異なる場合があります。
#pragma once
これをヘッダファイルの先頭に記述すると、一回だけインクルードするように制限することができます。
#pragma comment(lib,"path")
ライブラリファイルをリンクする際に使用する命令です。
これら以外にもいくつか#pragma指令がありますが、ほとんど使用例がないので紹介しません。
コンパイルを途中で止めてエラーメッセージを表示するには#errorを使用します。
#error エラーメッセージ
エラーメッセージを表示し、エラーとなります。
#include <stdio.h>
int main(void){
#error コンパイルを中止します
puts("Hello");
return 0;
}
実行結果
コンパイルエラーにより実行できません
エラー表示(筆者の環境の場合)
致命的エラー 3行目 error 指令: コンパイルを中止します(関数 main )
エラー 10行目 'printint' の再宣言で型が一致していない
その他のプリプロセッサ指令
#undefを使用すると、マクロの定義を取り消すことができます。同じマクロを2回定義するとエラーになるので、違う文字列や数値に置換したい場合は、一回#undefを使って定義を取り消す必要があります。
#include <stdio.h>
#define NUM 1
int main(void){
printf("NUM=%d\n",NUM);
#undef NUM
#define NUM 2
printf("NUM=%d\n",NUM);
return 0;
}
実行結果
NUM=1
NUM=2
処理系によってはこれ以外にもプリプロセッサ指令が定義されている場合があります。
コメント