In particular, will the following ever not work as expected:
typedef void(*func_p)(void*);
void foo(int* data)
{
printf("%i\n",*data);
}
int main(int argc, char** argv)
{
func_p bar;
int x = 42;
bar = foo;
bar((void*)&x);
return 0;
}
ie, can I rely on data pointers (void*, int*, struct baz*, but not neccesarily void(*)(void)) always being passed compatably?
It’s not required by the Standard that this works. The Standard requires that
char*andvoid*have the same representation and alignment requirements, all struct pointers do so and all unions pointers do so too. While it is undefined behavior to call the casted function pointer in any case (§6.5.2.2p9), the same representation and alignment requirements give a practical guarantee that the call works (§6.2.5p27).Other pointer types need not behave in such a way, though i haven’t personally met such a machine. It’s theoretically possible that an
int*has a smallersizeofthan achar*for example (ifinthas stricter alignment requirements thanchar, this could be a reasonable thing to do). Under the right calling convention, on such a machine it would be practically impossible to call a casted function pointer.