For two (or more) struct s: Base and Sub with a common first (unnamed) struct safe to convert / distinguish from Base to Sub and vice versa
struct Base{ struct{ int id;
Are these features guaranteed safe and technically correct? (Also: is the null term char data[] necessary and useful?)
struct Base * subToBase(struct Sub * s){ return (struct Base*)s; } struct Sub * baseToSub(struct Base * b){ if(b->id != SUB_ID){ return NULL; } return (struct Sub*)b; }
Edit
I do not plan to embed Base further in Sub , but leave the opportunity to add other subtypes (directly under Base ) later without changing Base . My main problem is whether it is safe to convert pointers to struct between "t21" and any under. References to the standard (C11) would be most appreciated.
Change v2
Changed wording slightly to discourage discussion of OOP / inheritance. What I want is tagged-union, without union , so it can be continued later. I have no plans to do additional nesting. Subtypes that need other subtype functions can do this explicitly, without any additional investment.
Context
For the script interpreter 1, I created a pseudo object oriented > tagged-union , without union . It has an (abstract) base type Object with several (specific) subtypes such as String , Number , List , etc. Each struct type has the following unnamed struct as the first member:
#define OBJHEAD struct{ \ int id; \ int line; \ int column; \ }
id identifies the type of object, line and column should (also) be understood. Simplified implementation of various objects:
typedef struct Object{ OBJHEAD; char data[]; // necessary? } Object; typedef struct Number{ OBJHEAD; int value; // only int for simplicity } Number; typedef struct String{ OBJHEAD; size_t length; char * string; } String; typedef struct List{ OBJHEAD; size_t size; Object * elements; // may be any kind and mix of objects } List; Object * Number_toObject(Number * num){ return (Object*)num; } Number * Number_fromObject(Object * obj){ if(obj->type != TYPE_NUMBER){ return NULL; } return (Number*)obj; }
I know that the most elegant and technically correct way to do this would be to use enum for id and union for different subtypes. But I want the type system to be extensible (through some form of type registry) so that types can be added later without changing all Object related code.
Late / external add may be:
typedef struct File{ OBJHEAD; FILE * fp; } File;
without changing the Object .
Are these conversions guaranteed to be safe?
(As for the small macro post: OBJHEAD will of course be widely documented, so additional developers will know which member names to not use. The idea is not to hide the title, but to save the insert time.)