I would keep the main code as is, and add code to generate an error after every call that creates a cast (hacking that code into the constructors should work, too, but given the constructor for an empty cast and the subclasses, that will lead to lower quality error messages).
I expect you will want to allow some/all implicit casts, explicit ones from and to void pointers, and downcasts from 'pointer to struct with first field of type t' to 'pointer to t'.
But most importantly: what class of programming errors are you thinking of? That class of error, IMO, either requires a daft programmer or horrendous source code that is full of casts.
Kind of by definition, what you would have would not be C, so there can't be any strictly-typed C implementations. I presume what you want is "just like C, except". And in fact, it's fine to want that. Just be aware that it really isn't C any more.