views:

129

answers:

2

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?

+7  A: 

It's not required by the Standard that this works. The Standard requires that char* and void* 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 smaller sizeof than a char* for example (if int has stricter alignment requirements than char, 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.

Johannes Schaub - litb
+1, although rather disappointing.
David X
@David quite frankly, if it means i would need to create dozens of wrapper functions just to be able to pass my function as parameter to such a type - i would just cast :)
Johannes Schaub - litb
@litb, been doing it that way for a while for exactly that reason :]
David X
`void foo(void *p) { int *data = p; ... }` is OK, though.
caf
@caf yes, definitely. If you have the choice to change the called function, then do that.
Johannes Schaub - litb
+1  A: 

Unless your code targets weird ancient mainframes, for all practical purposes it will work fine. No modern machine uses different representations for different pointer types, and I don't think it's realistic that any future machine ever will. It's simply illogical and backwards, much like ones-complement arithmetic.

If you're still worried or want to satisfy language purists, follow caf's suggestion.

R..
I was under the impression that pointers-to-functions may be a different size to pointers-to-data, or is that a c++ thing?
kibibu
It's a 16-bit Windows thing related to Microsoft's idea of "memory model" and near/far pointers. To clarify: the standard **allows** them to be different, but there's no reason they ever should be different on a modern architecture.
R..
@kibibu @R.. actually, having function pointers larger than data pointers is fairly common on microcontrollers and similar, since program memory may be separate from data memory and/or not writeable.
David X