void* and void(*)() are just not guaranteed to be the same size. If the latter is larger then those "implementation defined aspects" are what kicks in. It's nothing to do with the int.
In some systems functions are smaller, since they're gate addresses in a jump table (who has more than 64k functions?), so that's no problem.
But in some systems functions are bigger, and PCDOS systems running in real mode this was very common, and in those cases you'd need to get the extra bits from someplace else (union trick), or just design things another way.
In 1989 compilers weren't adversarial yet, and language specs weren't expected to be complete formal descriptions. The complete formal description was "whatever the compiler does" and "whatever the machine does" which was usually something sensible, unlike today.
I don't think it's bad enough to think of them as an adversary: I think letting the compiler do a little of the boring stuff is ok, and for the most part I am rarely surprised by this stuff. I don't -O3 and -funroll-loops and just forget-about-it either - I choose each of the -f options individually based on a combination of my understanding of what kinds of transformations they do, testing, and whether I am prepared to continuously keep those things in mind when programming.
What are you thinking of?