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++ のテンプレートの様に、同じ関数の型違いを生成できる。

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

前回次回