1

Cの別の構造内にさまざまなタイプの構造を埋め込むことは可能ですか?

基本的には、このようなことをしたいと思っています。

struct A { int n; void *config; }

struct AConfig { int a; char *b; }
struct BConfig { int a; float b; }

const struct A table[] = {
    { 103, (void*)(struct AConfig){ 1932, "hello" } },
    { 438, (void*)(struct BConfig){ 14829, 33.4f } }
}

これは C で可能ですか、それとも構造を個別に定義する必要がありますか?

4

4 に答える 4

4

いいえ、そのようには機能しません。構造ごとに明示的なストレージが必要です。

struct A { int n; void *config; };

struct AConfig { int a; char *b; };
struct BConfig { int a; float b; };

struct AConfig ac = { 1932, "hello" };
struct BConfig bc = { 14829, 33.4f };

const struct A table[] = {
    { 103, &ac },
    { 438, &bc }
};

編集:

もう 1 つの可能性は、名前付きイニシャライザunionと C99 ( ) を使用することです。-std=c99

enum config_type { CT_INT, CT_FLOAT, CT_STRING };

union config_value {
    int int_value;
    float float_value;
    const char* string_value;
};

struct config {
    enum config_type ctype;
    union config_value cvalue;
};

struct config sys_config[] = {
    { CT_INT, { .int_value = 12 }}, 
    { CT_FLOAT, { .float_value = 3.14f }}, 
    { CT_STRING, { .string_value = "humppa" }}};

void print_config( const struct config* cfg ) {
    switch ( cfg->ctype ) {
        case CT_INT: 
            printf( "%d\n", cfg->cvalue.int_value ); break;      
        case CT_FLOAT:
            printf( "%f\n", cfg->cvalue.float_value ); break;
        case CT_STRING:
            printf( "%s\n", cfg->cvalue.string_value ); break;
        default:
            printf( "unknown config type\n" );
    }       
}
于 2010-07-17T20:40:02.703 に答える
2

ユニオンを使用できます:

struct AConfig { int a; char *b; };
struct BConfig { int a; float b; };
struct A {
    int n;
    union {
        struct AConfig a;
        struct BConfig b;
    };
};

abがメモリ内のまったく同じスペースにあることに注意してください。したがって、を使用するA.a場合は使用しないでくださいA.b

これは無名共用体であるため、構造体 A の直接フィールドであるかのように、aとの両方を参照できます。b

struct A sa;
sa.n = 3;
sa.b.a = 4;
sa.b.b = 3.14;
于 2010-07-17T21:22:07.923 に答える
0

BConfigにbへのfloatポインターがある場合は機能します。

ちなみに、C構文に合うようにコードをリファクタリングする必要があるかもしれません。

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

typedef struct { int n; void *config; } Config;

typedef struct { int a; char *b; } AConfig;
typedef struct { int a; float *b; } BConfig;

int main(void) {
        AConfig A;
        BConfig B;
        A.a= 103;
        A.b= "hello";
        B.a= 438;
        B.b=(float *) malloc (sizeof(float));
        *(B.b)= 33.4f;
        const Config table[] = {
                { A.a, (void *) A.b },
                { B.a, (void *) B.b }
        };
        printf("Hi\n");
        return 0;
}
于 2010-07-17T20:00:57.387 に答える
0

あなたは組合を好むかもしれません。私のユニオン構文は少しさびていますが、次のようなものです:

union config { char* c; float d; };
struct A {int n; int a; union config b;};

const struct A table[] = {
    {103, 1932, { .c = "hello" } },
    {14829, 438, { .d = 33.4f } }
};

指定された初期化子 (表の .c または .d) には C99 が必要であり、char* または float にアクセスしているかどうかを明らかにする何らかの方法が必要ですが、それは別の場所でカバーされていると思います。

于 2010-07-17T21:16:05.170 に答える