Here's what I see in the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | struct brain_hero { entity *Head; entity *Body; entity *Glove; }; // ... only need one to point out the issue that I think I see ... struct brain { brain_id ID; brain_type Type; union { entity *Array; brain_hero Hero; brain_monstar Monstar; brain_familiar Familiar; brain_snake Snake; }; }; |
So here's the issue that I think I see (it's hard to describe without a whiteboard, but will do my best):
"brain_hero" is memory layout compatible with "entity *Segments[3]" because it is 3 "entity *" elements adjacent in memory, but is not memory layout compatible with "entity *Array".
To demonstrate, let's assume that we are really looking at "brain_hero" brain, but are accessing via the "Array" member.
Basically if you use Array[1], because you've used a union to type pun, it will basically be doing this: "((entity *)Hero.Head)[1]". Which is of course, not the same as Hero.Body, which is what would would have expected. Compilers can't really warn about this because the union says "this is what i want". And I suspect that any usage of Array (if any?) may have worked by being lucky.
Fortunately the fix is trivial. Simply change the definition to be like this instead:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | struct brain { brain_id ID; brain_type Type; union { entity *Array[1]; brain_hero Hero; brain_monstar Monstar; brain_familiar Familiar; brain_snake Snake; }; }; |
This will be memory layout compatible with the other types in the union. And accessing Array indexes beyond 1 is fine in practice (for the same reasons that the infamous "struct hack" works).