Entry

プログラミングメモ - 構造体でプリミティブ型をラップする

2009年04月11日

int も double も同じ配列に収めておきたいな……とかいうとき,C ではそのまま収めることができません。C++ では,抽象クラスを作って,各型をラップした子クラスでこれを継承すれば,同じ配列に収めることができるんですけど,C ではできません。つことで,C ではこんな風にやってみた。

#include <stdio.h>
#include <stdlib.h>

typedef enum OBJECT_TYPE_ {
    OBJECT_UNKNOWN = 0,
    OBJECT_INTEGER,
    OBJECT_REAL,
} OBJECT_TYPE;

typedef struct OBJECT_ {
    OBJECT_TYPE type;
    size_t size;
} OBJECT;

typedef struct INTEGER_ {
    OBJECT object;
    int value;
} INTEGER;

typedef struct REAL_ {
    OBJECT object;
    double value;
} REAL;

void
delete_object(OBJECT* p) {
    if (p != 0) {
        free(p);
    }
}

INTEGER*
create_integer(int n) {
    INTEGER* p = (INTEGER*)malloc(sizeof(INTEGER));
    if (p != 0) {
        p->object.type = OBJECT_INTEGER;
        p->object.size = sizeof(INTEGER);
        p->value = n;
    }
    return p;
}

REAL*
create_real(double n) {
    REAL* p = (REAL*)malloc(sizeof(REAL));
    if (p != 0) {
        p->object.type = OBJECT_REAL;
        p->object.size = sizeof(REAL);
        p->value = n;
    }
    return p;
}

int
main(int argc, char* argv[]) {
    OBJECT* p = (OBJECT*)create_integer(128);
    OBJECT* q = (OBJECT*)create_real(15.33);
    if (p != 0 && q != 0) {
        printf("[INTEGER]\n");
        printf("p->type: %d\n", p->type);
        printf("p->size: %d\n", p->size);
        printf("value  : %d\n", ((INTEGER*)p)->value);
        printf("\n");
        printf("[REAL]\n");
        printf("q->type: %d\n", q->type);
        printf("q->size: %d\n", q->size);
        printf("value  : %f\n", ((REAL*)q)->value);
    }
    delete_object(p);
    delete_object(q);
    return 0;
}

あまり難しいことはやってないんですけどね。

ともあれ,実行結果はこうなる。

% test
[INTEGER]
p->type: 1
p->size: 12
value  : 128

[REAL]
q->type: 2
q->size: 16
value  : 15.330000

OBJECT 型の構造体を定義して,これを子構造体 INTEGER,REAL のヘッダに持たせることで,OBJECT 型の型を持ちながら,各値を参照できるようになります。アライメントを少し意識しないといけないんだろうけれど,大抵のプラットフォームで動くんじゃないだろうか。

C++ でクラスを使う場合,タイプセーフであることやメンバアクセス(public とか protected とか)への配慮なんかが必要で,それも言語使用に組み込まれているけれど,C の場合は「それはプログラマが配慮すること」ということで,プログラマに丸投げすることになります。こゆのを手で組んでみると,「安全に使える仕組み」を提供すればするほど,実行速度が遅くなることを実感してしまう。いや,実際にパフォーマンスを測定してるわけじゃないですけどね。コードの量が増えるという意味で。

もっとも,この場合でも,配列を作るときは実体を収めることはできなくて,ポインタである OBJECT* 型で配列を作ることになりそうです。それはそれでちとアレなんですけど,ま,C でもそれっぽいことはできるということで。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN