C言語講座13回目。
今回は、C言語の豆知識その2です。
C言語のちょっとだけお得な豆知識
C言語で知っておくと便利な豆知識を。
関数ポインタのtypedef
カンマ(,)演算子
ヘッダの2重取り込みに注意
コメントよりも#ifdef
よく見かける、関数1個まるごとコメントは、/* */でやってるのをよく見かけます。
/* */ のコメントは通常ネストできないから、コメントを削除したりも必要になるし、面倒だったりします。
でも、そんな場合、そう苦労しなくともよい別の方法があります。
長い長いステートメントや関数丸ごといらなくなった。でも、将来的に使うかもしれないから残しておきたい。
そんなときは、コメントではなく#ifdef を利用するのです。
#ifdef _ZETTAI_DEFINE_SARETEINAI /* 絶対defineされていないもの */ void _MyDebug() { ... /* コメントもあるよ */ } #endif
これで、_MyDebug() 関数は、綺麗さっぱり消滅します。
関数ポインタのtypedef
C言語は、関数へのポインタが使えます。
便利に使うためには、関数ポインタのtypedef 宣言があります。
たとえば、
int func(char* s);
この関数ポインタの型タイプを定義するには、
typedef int (*PMYFUNCTYPE)(char* s);
とすれば、型としては、PMYFUNCTYPE として使えるようになります。
使い方としては、処理を共通化しておいて、一部の処理だけ差し替える時に、関数を入れ替えるという使い方や、ポインタ型にすることで、関数を配列や構造体の一つの属性として持たせたりとやれることが広がります。
下記は、処理を共通化する例です。
#include void CatTalk(char* s) { printf("%sは、ニャーニャーなく\n", s); } void DogTalk(char* s) { printf("%sは、ワンワンほえる\n", s); } typedef void (*PMYFUNCTYPE)(char* s); void Talk(PMYFUNCTYPE pfunc) { char name[128]; while(1) { name[0] = '\0'; printf("名前は? "); gets(name); if (name[0] == '\0') break; (*pfunc)(name); } } int main() { Talk(DogTalk); Talk(CatTalk); return 0; } 【実行結果】 >名前は? 犬 犬は、ワンワンほえる >名前は? > >名前は? 猫 猫は、ワンワンほえる >名前は?
カンマ(,)演算子
以外に知られていないものに、カンマ演算子があります。
1つのステートメントに複数の命令が記述できるものです。
例えば、for ループの先頭の初期化で、ループ先頭で初期化していることを明示するために、こんな書き方ができたりします。
for (iVal = 0, i = 0; i < 10; i++) {
....
}
この場合、別に、
iVal = 0;
for (i = 0; i < 10; i++) {
....
}
としても、動作に変わりはありませんが、並べて記述したときは、最後のステートメントの結果がその連続する式の値になります。
役に立つ例としては次のマクロ等。
#define CheckValue(x) func1(&x), func2(&x)
2つの関数を同時に呼び出したいときのマクロ
よく使われるのが、
#define CheckValue(x) { func1(&x);func2(&x); }
しかしこれだと if 文の中で使うことはできません。
if (CheckValue(x) == -1) { /* エラーになる */
....
}
カンマ演算子を使う場合は、if文でも利用できます。
ただ、わかりづらくなりますので、使うのは自己責任で。
知っていると、何かのときに応用がきくかも知れません。
ヘッダの2重取り込みに注意e
ヘッダファイルを2回取り込むと2重宣言エラーとか、意味不明のエラーが発生することがあります。
コンパイラによっては、#progma 指定でインクルードファイルの2重取り込みを抑止することができますが、通常の方法を念の為。
myheader.h の場合、
#ifndef _MYHEADER_H /* 次の define が通っていない場合のみ次文以降取込 */
#define _MYHEADER_H /* 一度取り込めばこの define が有効 */
各種宣言等
.......
#endif
これで、include 一回目のみ取り込みが実施されることになります。
今回はここまでにします。