Reputation: 80405
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.
Upvotes: 3
Views: 271
Reputation: 5796
would something like this work for you?
#define GROUPA elt0, elt1, elt2, elt3
#define GROUPB GROUPA, elt4, elt5
#define GROUPC GROUPA, elt6, elt7, elt8
#define GROUPD GROUPB, elt9, elt10, elt11
some_type group_A[] = {
GROUPA, NULL
};
some_type group_B[] = {
GROUPB, NULL
};
some_type group_C[] = {
GROUPC, NULL
};
some_type group_D[] = {
GROUPD, NULL
};
#undef GROUPA
#undef GROUPB
#undef GROUPC
#undef GROUPD
I think this is a perfect case to use macros to avoid code duplication while not sacrficing code clarity.
Upvotes: 2
Reputation: 110138
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:
struct ElementList {
struct ElementList *prefix; //Reference to elements of another array, or NULL
some_type *elements; //additional elements
};
This is more limited than the union
solution, but probably easier to use.
Upvotes: 1