I’m trying to come up with a way to declare several data structures that
are arrays of structures, where each subsequent array uses part of an earlier one.
way that minimizes duplication. That way each element is declared only once.
So conceptually, imagine these four arrays, where a given element number that
appears in both arrays is meant to represent the actual same thing, not just
another one with the same value.
some_type group_A[] = {
elt0, elt1, elt2, elt3, NULL
};
some_type group_B[] = {
elt0, elt1, elt2, elt3, // those are all A's
elt4, elt5, NULL // these are new to B
};
some_type group_C[] = {
elt0, elt1, elt2, elt3, // those are all A's
elt6, elt7, elt8, NULL // these are new to C
};
some_type group_D[] = {
elt0, elt1, elt2, elt3, elt4, elt5, // those are all B's
elt9, elt10, elt11, NULL // these are new to D
};
You can assume that some_type is already a typedef for some kind of structure.
What I would like to do is eliminate the redundant declarations, because they seem untidy in general and because they open you up to update incoherency. Here is the more compact representation, where an entry in a group can be a normal element or it can be a reference to another array of such elements.
(You would be right to infer by the NULL ponter at the end that each array declaration that each element is really a pointer to a structure of the same type.)
some_type group_A[] = {
elt0, elt1, elt2, elt3, NULL
};
some_type group_B[] = {
Group_A, elt4, elt5, NULL
};
some_type group_C[] = {
Group_A, elt6, elt7, elt8, NULL
};
some_type group_D[] = {
Group_B, elt9, elt10, elt11, NULL
};
In other words, I want a way to declare that Group_B and Group_C both begin with everything in Group_A, but then have their elements after that, and that Group_D contains everything in Group_B (itself in turn including everything in Group_A) and then adding its own elements.
I want this to be declarative, just a bunch of array data declarations, that happens at compile-time not a run-time bunch of data-structure-building code.
This would be forbidden from recursing, at least in practice and at run-time.
Is there a nice, declarative, looks-like-an-array implementation of this, or must I restort to some more complicated dynamic data structure implementation that isn’t all fixed at compile-time the way I prefer?
My hunch is that a tagged union of some sort may be the only way to go.
struct pointer_or_doublepointer {
int which_kind; // 0 == .element is valid; 1 == .table is valid
union {
real_type * element; // valid only when which_kind == 0
real_type ** table; // valid only when which_kind == 1
};
}
And then I would just make some_type a typedef for pointer_or_doublepointer.
Is this really the best way to set something like this up, or is there some
other better and more straightforward solution that comes to mind? Again, remember this is all supposed to be done via data declarations, not via code.
This is to be in pure C, not in C++ or some other variant.
Since you say that a reference to other arrays will only appear at the beginning, a simple way to represent this is to hold this reference separately from the rest of the elements:
This is more limited than the
unionsolution, but probably easier to use.