I thought that writing to one union member and reading from another is UB in C? Or does that apply only to members of different type?
Only in c++, not c. Unions (along with memcpy) are the ‘correct’ way to do type punning.
Not really. This discusses the issue, and Linus Torvalds is of the opinion that the standard is bad (warning: strong language).
It is (probably due to possible “trap values” ) but there’s a lot of code that assumes one can do that.
 In over 30 years of coding, I’ve yet to program on an architecture that has a “trap value”. I’ve yet to program on something other than a byte-oriented, 2’s complement machine.
Whether using the define or the union approach I’m having a hard time imagining this being worth it. The extra .sub.field just doesn’t seem that painful
if you need the bulk sub object handling as well. Maybe in a “it’s been 10 years of accretion this should have been a sub object all along, but I don’t want to touch all the consumers” kind of scenario? Does somebody have a concrete “in the wild” example?