0

The idea is that it is possible to make a pointer to an instance of Struct_A or
an instance of Struct_B with a pointer of the BaseStruct type.

Can I create a "base struct-type" in C as shown below with any compiler?
I tested it with GCC and it worked, but I am not sure if it would work everywhere ...

#include <stdio.h>

typedef enum {
 StructType_A,
 StructType_B
} StructType;

// >>> base type <<<
typedef struct {
 StructType type;
} BaseStruct;

// >>> type A <<<
typedef struct {
 StructType type;
 int xyz;
 char blabliblub;
} Struct_A;

// >>> type B <<<
typedef struct {
 StructType type;
 long int abc;
} Struct_B;

int main () {
 Struct_A a;
 BaseStruct* ptr;

 a.type = StructType_A;
 a.xyz  = 7853;
 a.blabliblub = 'z';

 ptr = (BaseStruct*) &a;

 if (ptr->type == StructType_A) printf ("YAY :3\n");
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
ikkowy
  • 13
  • 1
  • 3
    If your question is about C, don't cross-tag C++ unless there is something relevant to C++ (C != C++). – crashmstr May 17 '17 at 13:35
  • better to have the base struct as the first attribute of the derived ones as you may end up with more common attributes later on – Chris Turner May 17 '17 at 13:39
  • The base type is not used to store any data in it. Only to have access to type A or type B – ikkowy May 17 '17 at 13:41
  • 1
    Compile with `-pedantic` and see for yourself – Erik W May 17 '17 at 13:49
  • Too bad you only show snippets. But thought further you will end up violating the effective rule, invoking undefined behaviour. As you apparently have a predefined set of specialised structures, use a `union` inside your "base struct" instead. If you use gcc and can live with extensions, have a look at `-fplan9-extensions` which are a perfect alternative allowing an clean OOP approach. – too honest for this site May 17 '17 at 13:53
  • Ouh thanks - using a union is a great idea :3 – ikkowy May 17 '17 at 13:58
  • Possible duplicate of [Struct pointer compatibility](http://stackoverflow.com/questions/8702713/struct-pointer-compatibility) –  May 17 '17 at 14:16

1 Answers1

1

First, to answer your question, it is not allowed to point to a Struct_B type with a pointer of a BaseStruct type, if these two types have different alignment requirements (cf. C standard):

6.3.2.3 Pointers

(7) A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.

However, you can easily overcome this situation by building a proper union:

typedef enum {
    StructType_A,
    StructType_B
} StructType;

// >>> type A <<<
typedef struct {
    int xyz;
    char blabliblub;
} Struct_A;

// >>> type B <<<
typedef struct {
    long int abc;
} Struct_B;

// >>> composite type <<<
typedef struct {
    StructType type;
    union {
        Struct_A a;
        Struct_B b;
    } content;
} Union_AB;


int main () {
    Struct_A a;
    a.xyz  = 7853;
    a.blabliblub = 'z';

    Union_AB anA;
    anA.type = StructType_A;
    anA.content.a.xyz = 7853;
    anA.content.a.blabliblub = 'Z';

    Union_AB someB;
    someB.type = StructType_B;
    someB.content.b.abc = 5653L;

    Union_AB* ptr = (&anA);
    if (ptr->type == StructType_A) printf ("YAY :3\n");

    ptr = (&someB);
    if (ptr->type == StructType_A) printf ("YAY :3\n");

    return 0;
}
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58