On Aug 23, 2018, at 3:17 PM,
<ron(a)ronnatalie.com> <ron(a)ronnatalie.com> wrote:
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.
Note that this is a legitimate use of union. That is,
unless I misunderstood what you meant by it, there is
no "conversion by union" as you call it or "cheating"
as I call it or type punning. There is no put one thing
in and take another thing out. Now it may be that
someone misused such a union. This is easy to do as,
unlike Pascal, C has no tagged variant record & it is
user's responsibility to use it right.
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).
From what I recall {c,m,re}alloc() returned a char*, not a void *.
I don't have K&R1 handy at the moment so can't recall if void* was
mentioned in the book (if not, that could be one reason for a lack of
its use).