0

ネストされた構造体を使用して、プレーンCで一種の「構造体継承」を作成しています。たとえば、次のような構造体がいくつかあります。

struct a {
    obj_type type_id;
    int x;
    int y;
}

struct b {
    struct a super;
    char* str;
}

struct c {
    struct a super;
    int* data;
    bool flag;
}

次に、次のように列挙型を作成します。

typedef enum {
    OBJ_TYPE_A,
    OBJ_TYPE_B,
    OBJ_TYPE_C
} obj_type;

これにより、さまざまなオブジェクトがどの構造体であるかを確認しtype_id、対応する構造体にキャストすることで、継承をシミュレートできます。私の問題は、親構造体のプロパティを手動で定義xせずに、これらの「子」構造体を初期化できるようにしたいということです。y

基本的に、私はこのようにポインタを初期化することができます:

struct b obj_b = { OBJ_TYPE_B, 0, 0, "foo" };
struct b *ptr_b = malloc(sizeof(struct b));
memcpy(ptr_b, &obj_b, sizeof(struct b));

ただし、初期化を行う関数がa必要なので、次のようにすることができます。

struct b *ptr_b = object_create(OBJ_TYPE_B, { "foo" }, sizeof(struct b));

私はこのような関数の実装のようなものを作成しました:

const struct a DEFAULT_A = { OBJ_TYPE_A, 0, 0 };

struct a object_create(obj_type type, void* data_ptr, size_t size) {
    struct a new_obj = malloc(size);
    memcpy(new_obj, &DEFAULT_A, sizeof(struct a));
    memcpy(new_obj + sizeof(struct a), data_ptr, size - sizeof(struct a));
    return new_obj;
}

ただし、次のようなことを行う方法がないため、これを実際に使用することはできません。

struct b *ptr_b = object_create(OBJ_TYPE_B, &{ "foo" }, sizeof(struct b));

関数に渡す一種の「匿名」データブロックを作成する方法はありますか?それとも、仕事をするためにマクロのようなものに頼らなければなりませんか?

4

1 に答える 1

3

あなたが望むことは確かにC99で可能です。上記はたとえば機能します。構造体リテラルをキャストする必要があります。

#include <stdio.h>

struct s {
    char *a;
};

void f(struct s *p)
{
    printf("%s\n", p->a);
}


int main()
{
    f(&(struct s){ "hello world" });
    return 0;
}

この記事のトピックの詳細:

複合リテラルは左辺値を生成します。これは、複合リテラルによって宣言された名前のないオブジェクトのアドレスである複合リテラルのアドレスを取得できることを意味します。複合リテラルにconst修飾型がない限り、ポインターを使用して変更できます。

于 2012-12-31T20:13:26.583 に答える