Can I 'extend' a struct in C?

后端 未结 7 1464
太阳男子
太阳男子 2020-12-08 16:05
typedef struct foo_s {
    int a;
} foo;

typedef struct bar_s {
    foo;
    int b;
} bar;

Essentially I want to do:

bar b;
b.a;
<         


        
相关标签:
7条回答
  • 2020-12-08 16:36

    You can, using pointers, because a pointer to a structure object is guaranteed to point its first member. See e.g. this article.

    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct foo_s {
        int a;
    } foo;
    
    typedef struct bar_s {
        foo super;
        int b;
    } bar;
    
    int fooGetA(foo *x) {
      return x->a;
    }
    
    void fooSetA(foo *x, int a) {
      x->a = a;
    }
    
    int main() {
      bar* derived = (bar*) calloc(1, sizeof(bar));
      fooSetA((foo*) derived, 5);
      derived->b = 3;
      printf("result: %d\n", fooGetA((foo*) derived));
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 16:38

    Evidently this feature has been added to C11, but alas I don't have access to a C compiler of recent vintage (>= GCC 4.6.2).

    typedef struct foo {
      int a;
    } foo;
    
    typedef struct bar {
      struct foo;
      int b;
    } bar;
    
    int main() {
      bar b;
      b.a = 42;
      b.b = 99;
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 16:40

    Not possible in C the way you did. But you can mimic inheritance having a foo member variable in bar.

    typedef struct bar_s {
        foo obj;
        int b;
    } bar;
    
    bar b;
    b.obj.a = 10;
    
    0 讨论(0)
  • 2020-12-08 16:44

    If you ment

    typedef struct foo_s {
        int a;
      } foo;
    
    typedef struct bar_s {
     foo my_foo;
    int b;
    } bar;
    

    so you can do:

    bar b; b.my_foo.a = 3;
    

    Otherwise, There's no way of doing it in C since the sizeof(bar_s) is detriment on compile time. It's not a good practice but you can save a void * ptr; pointer within bar_s, and another enum which describes the ptr type, and cast by the type.

    i.e:

    typedef enum internalType{
      INTERNAL_TYPE_FOO = 0,
    }internalType_t;
    
    typedef struct bar_s {
     internalType_t ptrType;
     void* ptr;
    int b;
    } bar;
    

    and then:

    bar b;  foo f;
    b.ptrType = INTERNAL_TYPE_FOO;
    b.ptr = &f;
    

    and some where else in the code:

     if (b.ptrType == INTERNAL_TYPE_FOO) {
        foo* myFooPtr = (foo *)b.ptr;
     }
    
    0 讨论(0)
  • 2020-12-08 16:46

    It can be easily done via preprocessor:

    Create a file named base_foo.h:

    int foo;
    

    Then simply include it:

    typedef struct foo_s {
        #include "base_foo.h"
    } foo;
    
    typedef struct bar_s {
        #include "base_foo.h"
        int b;
    } bar;
    
    0 讨论(0)
  • 2020-12-08 16:50

    You can try using inheritance:

    struct foo_s
    {
        int a;
    };
    
    struct bar_s: foo_a
    {
        int b;
    };
    

    Works in C++, not sure if it works in C.

    0 讨论(0)
提交回复
热议问题