C 言語 マクロ講座 ## 実用編2007年03月20日 13時00分33秒

## の使い方だが、個人的に主に使うのは次の二つの場合だ。型違いの同じ関数をいくつも作りたい時。そして、複数の関数ポインタを含む構造体の配列を初期化する時。今回は前者の例をあげる。

各型に適した fread と fwrite を書くことにしよう。今回は、int 型、char 型と double 型を実装する。


% cat read_x.c
#ifndef LIB
        #include 
#endif

#define FREAD(type) \
    size_t fread_ ## type(void *p, FILE* fd) \
    { \
        return fread(p, sizeof(type), 1, fd); \
    }

#define FWRITE(type) \
    size_t fwrite_ ## type(void *p, FILE* fd) \
    { \
        return fwrite(p, sizeof(type), 1, fd); \
    }

FREAD(int)
FREAD(char)
FREAD(double)
FWRITE(int)
FWRITE(char)
FWRITE(double)

int main()
{
    int i = 1;
    char c = 'c';
    double d = 3.14;

    char *filename = "temp.txt";
    FILE *in, *out;

    out = fopen(filename, "w");
    fwrite_int(&i, out);
    fwrite_char(&c, out);
    fwrite_double(&d, out);
    fclose(out);

    i = 0; c = 0; d = 0;
    printf("i = %d, c = %c, d = %f\n", i, c, d);

    in = fopen(filename, "r");
    fread_int(&i, in);
    fread_char(&c, in);
    fread_double(&d, in);

    printf("i = %d, c = %c, d = %f\n", i, c, d);
}
% make read_x
cc -O2 -fno-strict-aliasing -pipe   read_x.c  -o read_x
% ./read_x 
i = 0, c = , d = 0.000000
i = 1, c = c, d = 3.140000

プリプロセッサを通して見る。


% gcc -E -DLIB read_x.c
# 1 "read_x.c"
# 1 ""
# 1 ""
# 1 "read_x.c"
# 17 "read_x.c"
size_t fread_int(void *p, FILE* fd) { return fread(p, sizeof(int), 1, fd); }
size_t fread_char(void *p, FILE* fd) { return fread(p, sizeof(char), 1, fd); }
size_t fread_double(void *p, FILE* fd) { return fread(p, sizeof(double), 1, fd);
 }
size_t fwrite_int(void *p, FILE* fd) { return fwrite(p, sizeof(int), 1, fd); }
size_t fwrite_char(void *p, FILE* fd) { return fwrite(p, sizeof(char), 1, fd); }
size_t fwrite_double(void *p, FILE* fd) { return fwrite(p, sizeof(double), 1, fd
); }

int main()
{
 int i = 1;
 char c = 'c';
 double d = 3.14;

 char *filename = "temp.txt";
 FILE *in, *out;

 out = fopen(filename, "w");
 fwrite_int(&i, out);
 fwrite_char(&c, out);
 fwrite_double(&d, out);
 fclose(out);

 i = 0; c = 0; d = 0;
 printf("i = %d, c = %c, d = %f\n", i, c, d);

 in = fopen(filename, "r");
 fread_int(&i, in);
 fread_char(&c, in);
 fread_double(&d, in);

 printf("i = %d, c = %c, d = %f\n", i, c, d);
}

## マクロを使うと C++ のテンプレートの様に、同じ関数の型違いを生成できる。

この様な使い方の欠点は二つ。一、デバッグが少々難しい。二、関数の定義にマクロを使っているため、定義に見えない。

前回次回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2007/03/20/1327981/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。