C言語のプリプロセッサディレクティブとは?3つの分類と使い方をわかりやすく解説
プリプロセッサ(preprocessor)とは、ソースコードがコンパイラに渡される前に処理を行うプログラムのことです。さまざまな命令文(ディレクティブ)の制御のもとで動作します。
プリプロセッサディレクティブは、ソースプログラムのmain関数より前に記述するのが一般的です。行の先頭(第1カラム)に記号「#」で始まり、文末にセミコロン(;)は不要という点に注意しましょう。
よく使われるプリプロセッサディレクティブには、以下のようなものがあります。
- #define
- #undef
- #include
- #ifdef
- #endif
- #if
- #else など
これらのプリプロセッサディレクティブは、その役割によって次の3つに分類できます。
- マクロ置換ディレクティブ(Macro Substitution)
- ファイル取り込みディレクティブ(File Inclusion)
- コンパイラ制御ディレクティブ(Compiler Control)
マクロ置換ディレクティブ
#define を使うと、識別子(マクロ名)に任意の文字列を定義できます。コンパイル前に、ソースコード内の識別子がすべて定義済みの文字列へと機械的に置き換えられます。
構文
#define 識別子 文字列
記述例
単純なマクロの例:
#define MAX 500
引数付きマクロの例:
#define SQRT(x) x*x
ネスト(入れ子)マクロの例:
#define A 10 #define B A+1
この場合、B は「A+1」、すなわち「10+1」に置き換えられます。このようにマクロを別のマクロで定義することも可能です。
ファイル取り込みディレクティブ
#include を使うと、指定したファイルの内容をその位置にそのまま挿入できます。標準ライブラリのヘッダファイルや自作ヘッダの読み込みに利用されます。
構文
#include "ファイル名" または #include <ファイル名>
「" "(二重引用符)」で囲んだ場合は、まず現在のディレクトリを検索し、見つからなければ標準インクルードディレクトリを検索します。一方「< >」で囲んだ場合は、標準インクルードディレクトリのみが検索されます。
記述例
#include <stdio.h> #include "FORM.C"
コンパイラ制御ディレクティブ
これらのディレクティブは、コンパイラの動作そのものを制御するために使用します。C言語のプリプロセッサには「条件付きコンパイル(conditional compilation)」という機能があり、プログラム内の特定の行や行のグループを、条件に応じてコンパイル対象に含めたり除外したりできます。
代表的なものに #ifdef と #ifndef があります。
#ifdef の使用例
#include <stdio.h>
#define DEBUG
int main(void) {
#ifdef DEBUG
printf("デバッグモードが有効です\n");
#endif
printf("通常の処理を実行します\n");
return 0;
}
この例では、DEBUG が #define で定義されている場合に限り、最初のprintf文がコンパイルされます。#undef で定義を解除すれば該当部分を簡単に無効化できるため、デバッグ作業や実行環境ごとのコード切り替えに非常に便利です。
-
C言語におけるユニオンとポインタの使い方を徹底解説
ユニオン(共用体)とは、異なるデータ型を持つ複数の変数が、同一のメモリ領域を共有するための仕組みです。構造体が各メンバーごとに独立したメモリを割り当てるのに対し、ユニオンではすべてのメンバーが同じアドレスを参照するという点が大きな特徴です。 ユニオンの構文 ユニオンを定義するときの基本的な書式は次の通りです。 union タグ名{ データ型 メンバー1; データ型 メンバー2; ---- ---- データ型 メンバーn; }; 実際の記述例を見てみましょう。 union sample{ int a; float b; char
-
C言語のポインタ入門!宣言・初期化から配列アクセスの実例まで徹底解説
ポインタ(pointer)とは、他の変数のメモリアドレスを格納するための変数です。C言語においてポインタは、メモリを直接操作したり、関数間でデータを効率的にやり取りしたりするために欠かせない重要な概念です。 ポインタの宣言・初期化とアクセス まず、次のような通常の整数変数の宣言を見てみましょう。 int qty = 179; 変数qtyには値「179」が格納されると同時に、メモリ上のどこかにその格納場所(アドレス)が割り当てられます。 ポインタの宣言 int *p; 「p」はポインタ変数であり、別の整数型(int)変数のアドレスを保持します。変数名の前にアスタリスク(*)を付けることで、「こ