3) It's very rare in practice that the only pointer to your object (which you
still plan to access later) to be stored in a void[]-allocated array! Remember,
the properties of memory regions are determined when the memory is allocated,
so casting an array of structures to a void[] will not lose you that reference.
You'd need to move your pointer to a void[]-array (which you need to allocate
explicitly or, for example, concatenating your reference to the void[]), then
drop the reference to your original structure, for this to happen.
void[] = can contain pointers
ubyte[] = can not contain pointers
void[] just wraps void*, which is a low level type and can contain
anything. Because of that, the conservative GC needs to scan it for
pointers. ubyte[], on the other hand, contains sequences of 8 bit
integers. For untyped binary data, ubyte[] is the most correct type.
You want to send it over network or write it into a file? Use ubyte[].
The data will never contain any pointers. You want to play low level
tricks, that involve copying around arbitrary memory contents (like
boxing, see std.boxer)? Use void[].
I think that's a good way to distinguish it.
You shouldn't cast structs or any other types to ubyte[], because the
memory representation of those type is highly platform specific. Structs
can contain padding, integers are endian dependend... If you want to
convert these to binary data, write a marshaller. You _never_ want to do
direct casts, because they're simply unportable. If you do the cast, you
have to know what you're doing.