C言語

#defineとマクロ関数の基本

C言語には、**「#define(ディファイン)」という「コンパイルする前に文字を置き換える命令」があります。
今回は、この#defineの基本的な使い方を解説します。

#defineとは

#(シャープ)で始まる命令は、プリプロセッサ命令と呼ばれます。
これは、コンパイルの前に実行される特別な命令で、ソースコードをコンパイルしやすい形に“準備”するためのものです。
その中のひとつである #define は、「特定の文字を別の文字列に置き換える」命令です。

#defineの構文は次の通りです。

#define マクロ名 置換する文字列または数値

プログラムで使用する例は次の通りです。

#include <stdio.h>
#define PI 3.141592

int main(void)
{
    printf("円周率は %f です。\n", PI);
    return 0;
}

printf 関数の PI の箇所は、実際には、コンパイルのときに次のように変換されます。

printf("円周率は %f です。\n", 3.141592);

これだと、直接数値を記述して変わらないように感じますが、PI を複数個所で使用した場合、値の修正が必要になった場合、#defineの値を直すだけ済みます。

マクロ名の付け方

C言語では、定数の名前(マクロ名)は、大文字で書くのが一般的です。
ひと目見て、定数なのか、変数なのかがわかるためです。
また、次のように、複数の単語をつなぐときは、アンダースコア( _ )区切ります。

#define TAX_RATE 0.1
#define MAX_SPEED 120
#define BUFFER_SIZE 256

マクロ関数とは

#define は「定数」だけでなく、「式」も登録できます。
そのときに、まるで関数のように使える形をマクロ関数といいます。

わかりにくいので、次に例を示します。

#define SQUARE(x) ((x) * (x))

SQUARE(x)(x) の部分は、関数でいう引数のようなものです。
SQUARE(5)のように使うと、x5 に置き換えられます。
つまり、関数に見えますが、実際には、文字の置き換えをしているだけです。

このマクロ関数を使用するときは、次のようになります。

printf("%d\n", SQUARE(5));   // 25
printf("%d\n", SQUARE(2+3)); // 25

これは内部では次のように置き換えられます。

SQUARE(5)   →  ((5) * (5))
SQUARE(2+3) →  ((2+3) * (2+3))

マクロ関数の注意点

マクロはただの文字の置き換えなので、カッコを忘れると変な結果になります。

悪い例:

#define SQUARE(x) x * x

printf("%d\n", SQUARE(2+3)); // 2+3*2+3 = 11 (本当は25にしたい)

このように、本当なら、(2+3) * (2+3)としたいのに、2+3*2+3 となってしまいます。

良い例:

#define SQUARE(x) ((x) * (x))

このように、マクロを書くときは、引数には (x)、全体も ((x) * (x))のように必ずカッコで囲むようにしましょう。

まとめ

  • #define は「コンパイル前に文字を置き換える命令」
  • 定数をまとめるのに便利(例:#define TAX 0.1
  • 関数のように書ける「マクロ関数」もある(例:#define SQUARE(x) ((x)*(x))
  • カッコの付け忘れで思わぬ動作になることがある
  • 複雑な処理は、マクロよりも普通の関数を使うほうが安全

-C言語