There's an odd (but useful) idiom in C that is often found. And you may find it useful here.
typedef union {
short int x;
float y;
unsigned char z[1];
} MyUnion;
int main( int argc, char *argv[] ) {
MyUnion s;
s.x = 1000;
printf("%u %u %u\n", sizeof(MyUnion), s.z[0], s.z[1]);
return 0;
}
Note that you don't even need to specify the actual extent of z[]. Sizing it to one meets the modern standard for syntax. Exceeding the boundary of any array at run-time is undefined behavior, but so will be using an array to index through any declaration as endian nature and padding/alignment issues are target-dependent, anyway.
The use of indices outside the given boundary are found in c-compiler code, libraries (malloc, for example, often uses [-1] as an array index), operating systems, and elsewhere. It's quite common, for example, to find in the use of:
typedef struct {
int typecode;
int len;
char s[1];
} packet_t;
for network packets, object file records, etc. The actual allocation is done through malloc, though, to ensure that the proper size exists. It's not wrong and it's often done.
Since it is part of a union, it will start at the beginning. But the size of the union will be determined by the largest item and not by it.
C does require that any object have a unique address. So if the union has no other definitions inside of it, then creating an instance of the object will require space. But this is to merely meet the requirement that different instances have different addresses.
If I were simply trying to create a byte array that maps a union of object(s), I'd definitely NOT bother with a sizeof() operator, at all. I'd just write it like I did above. Saves text and saves the risk of having to edit that line if I change the name of something.