代码之家  ›  专栏  ›  技术社区  ›  Thomas O

是否可以将变量类型的结构“嵌入”到另一个结构中(合同通用条款)

  •  1
  • Thomas O  · 技术社区  · 14 年前

    在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 回复  |  直到 14 年前
        1
  •  3
  •   Nikolai Fetissov    14 年前

    不,不是这样的。每个结构都需要显式存储:

    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 }
    };
    

    编辑:

    另一种可能性是利用 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" );
        }       
    }
    
        2
  •  1
  •   R Samuel Klatchko    14 年前

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

    请注意 a b 在记忆的同一个空间里。所以如果你要用 A.a 你不应该使用 A.b 反之亦然。

    因为这是一个匿名联盟,所以您可以同时引用这两个联盟 好像它们是结构A的直接字段:

    struct A sa;
    sa.n = 3;
    sa.b.a = 4;
    sa.b.b = 3.14;
    
        3
  •  0
  •   luiscubal    14 年前

    如果BConfig有一个指向b的浮点指针,它就会工作。

    顺便说一句,也许你需要重构你的代码以适应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;
    }
    
        4
  •  0
  •   Karl Bielefeldt    14 年前

    你可能更喜欢工会。我的union语法有点生疏,但有点像这样:

    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 } }
    };