Cプログラマへの道 #11 - マクロ

Last Edited: 8/14/2024

このブログ記事では、C言語におけるマクロついて紹介します。

C Macros

オブジェクト型マクロ

最初の記事で、定数を定義するもう一つの方法として#defineを簡単に紹介しました。これはオブジェクト型のマクロの例です。

# define PI 3.14
 
int main() {
    int radius = 2;
    printf("Area: %.3f\n", radius*radius*PI); // => Area: 12.560
 
    return 0;
}

前に説明したように、プリプロセッサはコンパイルの前にすべての「PI」マクロを3.14に置き換えます。マクロは、 型宣言を明示せずに定数を作成できる方法で、通常は良い方法とは言えませんが、時には必要です。

関数型マクロ

マクロは定数を定義することに加えて、次のようにマクロを使って関数を定義することもできます。

# define PI 3.14
# define area(r) r*r*3.14
 
int main() {
    int radius = 2;
    printf("Area: %.3f\n", area(radius)); // => Area: 12.560
 
    double dRadius = 2.5;
    printf("Area: %.3f\n", area(dRadius)); // => Area: 19.625
 
    return 0;
}

オブジェクト型マクロが型に依存しないのと同様に、関数型マクロも入力の型を気にしません。また、 マクロは単なるテキスト置換であるため、通常の関数のように入力パラメータをメモリに保存する必要がありません。 関数型マクロは複数の引数を取ることもできます。

# define findMax(array, length) ({ \
    typeof(array[0]) curMax = array[0]; \
    for (int i = 0; i < length; i++) { \
        if (array[i] > curMax) { \
            curMax = array[i]; \
        } \
    } \
    curMax; \
})
 
int main() {
    int array1[4] = {5,7,9,1};
    printf("Max: %d\n", findMax(array1, 4)); // => Max: 9
 
    double array2[4] = {0.33, 1.94, 8.34, 3.14};
    printf("Max: %.2f\n", findMax(array2, 4)); // => Max: 8.34
 
    return 0;
}

関数型マクロを使用する際には、マクロが単なるテキスト置換であるため、returnステートメントを含まないことを注意する必要があります。

条件付きコンパイルディレクティブ

デバッグ用に特定の関数を使用したい場合、値が0または1のいずれかを取るDEBUG_MODEオブジェクト型マクロを定義し、 次のような条件付きコンパイルディレクティブを使用できます。

# define DEBUG_MODE 1
 
int main() {
	
    #if DEBUG_MODE == 1
	printf("DEBUG_MODE! \n");
    #elif DEBUG_MODE == 0
	printf("NOT DEBUG_MODE! \n");
    #else
	printf("???\n");
    #endif
 
    return 0;
}

また、オブジェクト型マクロDEBUG_MODEが定義されているかどうかを確認するためにdefined()#ifdef、または#ifndefを使用することもできます。

# define DEBUG_MODE
 
int main() {
	
    #if defined(DEBUG_MODE)
	printf("DEBUG_MODE! \n");
    #endif
 
    #ifdef DEBUG_MODE
	printf("DEBUG_MODE! \n");
    #else
	printf("NOT DEBUG_MODE! \n");
    #endif
 
    #ifndef DEBUG_MODE
	printf("NOT DEBUG_MODE! \n");
    #endif
 
    return 0;
}

上記の方法は、DEBUG_MODEに特定の値を取らせるよりもシンプルです。条件付きコンパイルディレクティブを使用して、条件に応じてオブジェクト型マクロ に異なる値を設定することもできます。

クイズ

この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。

リソース