Comment by jcranmer
5 months ago
C23 §6.5.2.2p7
> If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined.
Compatible types requires integrating texts from several different paragraphs, but the general notion is "identical type, in a frontend sense", not "same ABI." This means that "const void " and "void " are not compatible types, much less "void " and "struct foo ".
I get that it's defined that way, but I'd really like to know why.
I can see the value in saying that struct x* isn't compatible with struct y*, because they could have different alignment or packing rules. But struct x* and void*, which is already special-cased to allow assignment without a cast? Why aren't these considered compatible in function pointer parameter definitions?
Is there any work involved in casting void* to struct* (on any architecture) that a plain function pointer would miss out?
Yes, some restrictions seem arbitrary. Just like why these two types are not compatible:
I know, I know, changing it would break existing code, etc.
You jest, but a central feature of C is that void* is a universal pointer, and can be used as the basis of polymorphism and context passing. That's why you can do things like:
It would be nice to write:
But instead we have to write this to avoid being declared "undefined behaviour":
So what is the upside of having this rule, given the same thing is going to happen anyway, just more verbose?