I haven't done much BSD kernel programming in
last 15 years but this is
not my recollection. BSD used caddr_t, typedefed to char*,
sort of as void
*. IIRC void*
came in common use after BSD unix first came about. Why
use a union when a
cast will do? :-) The union trick is more likely to be used for
esoteric
things
(like getting at fl.pt. bytes) or for more complex
types or probably by
people with lots of programming experience in pascal and not so
much in C
(in Pascal
you *had* to use untagged variant records if you wanted
to cheat!). In C,
all that void* does is allow you to avoid casts in some cases.
Your recollections are certainly wrong. I spent a lot of time tracing
down why the Kernel crashed doing I/O and traced it to this and spent a
while undoing it as I stated.
This union was right in the middle of the buf struct:
union {
caddr_t b_addr; /* low order core address */
int *b_words; /* words for clearing */
struct filsys *b_filsys; /* superblocks */
struct dinode *b_dino; /* ilist */
daddr_t *b_daddr; /* indirect block */
} b_un;
There were a number of other places that did the same thing. It's
OFFICIALLY now in undefined behavior by the standard (though of course that
didn't exist in the BSD days) ,
to store in one element of the union and retrieve it via another. This is
one of the reasons why.
This isn't the only place it occurs.
Void* came out with the V7 compiler, if I recall properly. The BSD kernel
looks as if it requires such a later compiler (it uses bit fields which the
earlier compilers didn't support).
But it doesn't matter. You are right char* (or caddr_t) would work just
fine for this albeit with some explicit casting.