If I declare a Union as:
union TestUnion
{
struct
{
unsigned int Num;
unsigned char Name[5];
}TestStruct;
unsigned char Total[7];
};
Short answer: there is no way except by adding an enum somewhere in your struct outside the union.
enum TestUnionPart
{
TUP_STRUCT,
TUP_TOTAL
};
struct TestUnionStruct
{
enum TestUnionPart Part;
union
{
struct
{
unsigned int Num;
unsigned char Name[5];
} TestStruct;
unsigned char Total[7];
} TestUnion;
};
Now you'll need to control creation of your union to make sure the enum is correctly set, for example with functions similar to:
void init_with_struct(struct TestUnionStruct* tus, struct TestStruct const * ts)
{
tus->Part = TUP_STRUCT;
memcpy(&tus->TestUnion.TestStruct, ts, sizeof(*ts));
}
Dispatch on the correct values is now a single switch:
void print(struct TestUnionStruct const * tus)
{
switch (tus->Part)
{
case TUP_STRUCT:
printf("Num = %u, Name = %s\n",
tus->TestUnion.TestStruct.Num,
tus->TestUnion.TestStruct.Name);
break;
case TUP_TOTAL:
printf("Total = %s\n", tus->TestUnion.Total);
break;
default:
/* Compiler can't make sure you'll never reach this case */
assert(0);
}
}
As a side note, I'd like to mention that these constructs are best handled in languages of the ML family.
type test_struct = { num: int; name: string }
type test_union = Struct of test_struct | Total of string