C言語 プログラミング

C言語でプリプロセッサ/マクロを使う【C言語プログラミング基礎編(6)】

C言語講座6回目、他の言語になくて、C言語では強力なパワーを発揮するのが、プリプロセッサ、とくにdefine マクロです。

#define ではじまるおまじないについては、以前はその使い方で何冊も書籍がでていました。

下手に使うとプログラムがわからなくなるものの、上手に使えばこれほど便利なものもありません。

今回は、そのマクロの導入部分をご紹介します。

C言語でプログラミング:プリプロセッサ/マクロの使い方

C言語プリプロセッサ

基本構文

マクロは、#で始まるプリプロセッサの命令です。

主なプリプロセッサ命令を列挙します。

ファイル取り込み
#include <(ファイル名)>
#include "(ファイル名)"
自分のプロジェクト内などで使う場合は、””で、システムや外部ライブラリなどから提供されるものであれば < > を使います。

文字列の置き換え
#define (文字列1) (文字列2)

文字列置き換え(#define)の取り消し
#undef (識別子名)

識別子が定義されているか(#ifdef)、未定義か(#ifndef)の判定
#ifdef (識別子名)
(識別子名)が定義されていれば、この部分が有効
#endif

#ifndef (識別子名)
(識別子名)が定義されていないれば、この部分が有効
#endif

マクロの条件判定
通常の言語のように条件分岐も使えます。
#if~#elif~#else~#endif
上記で説明した、#ifdef、#ifndef のようにつかうために、definedが用意されていて

#if defined( (識別子) )
(識別子名)が定義されていれば、この部分が有効
#endif

C言語マクロ利用方法(#define)

一般的な使い方(とりあえず初級編)は、配列を定義するための領域の長さを指定する方法です。


#define  CONSTANT_VALUE    128


int iAry[CONSTANT_VALUE];

for (i = 0; i < CONSTANT_VALUE; i++) {
	printf("Ary[%d] = %d\n", iAry[i]);
}

これだと、配列の上限の修正は、マクロ定義の数字を変更し再コンパイルすれば済むので、修正忘れも防ぐことができます。

さらには、文字列の固定値を定義して使う方法です。


#define KEY1      "KEY1"
#define KEY2      "KEY2"
#define FILENAME  "file.txt"

int iValue;
iValue = GetPrivateProfileString(KEY1, KEY2, 0, FILENAME);

ただし、この場合、マクロは必ずその場所に展開されてしまうこと、および、デバッグ時に変数名としてアクセスしたり、領域を少しでも節約することを考えると、変更ができない定数として指定することの方が実用性は高いかもしれません。


const char  szKey1[] = "KEY1";
const char  szKey2[] = "KEY2";
const char  szFileName[] = "file.txt";

また、昔のソースコードを追いかけてたら、時折みかけるのがprintf 関係のフォーマットのマクロ定義をよく見かけました。


#define MYFORMAT   "%s"

sprintf(szBuf, MYFORMAT, szStr1, szStr2);

#define は置き換えなので、こういうこともできてしまいますが、正直これはやりすぎだと思います。

printf関係は、%sと引数の数が異なると(特に引数が少ない場合)アプリケーションエラーを発生させる原因になるからです。

とはいっても何度も使用するのであれば、確かに定義したくなるのかもしれません。

この場合は、先ほど述べた、const charの定義の方が向いていると思います。


const char szFormat[] = "%s";
int func()
{
	......
	sprintf(szBuf, szFormat, szStr1, szStr2);
	......
}

といった具合です。

わかりにくくなること、間違いを避けることを考慮しながら時と場合に応じて使い分けることが重要です。

 

C言語マクロ利用方法(#ifdef)

デバッグの時によく利用されるのが、マクロの条件文です。


#define MyDEBUG 

#ifdef MyDEBUG

fprintf(stderr, "デバッグで使う情報[%s]\n", info0);

#else

/* なにもしない */

#endif

#define MyDEBUGを消してしまえば、プリント文ははずれて、何もしなくなります。
※コンパイラのオプション指定でも、定義したり、しなかったりが可能です。

 

今回はここまで。
C言語の話は、この後も何回かに分けて投稿しますので、興味のある方は引き続きよろしくお願いします。

-C言語, プログラミング

Copyright© SIMPLEONESOFT (BLOG) , 2022 All Rights Reserved.