6 ms·
It has to do with getting an int from pointer arithmetic on function pointers. IIRC, there's no guarantee that a function pointer will even fit in any specific
by silentbicycle 16y ago
It has to do with getting an int from pointer arithmetic on function pointers. IIRC, there's no guarantee that a function pointer will even fit in any specific kind of int. On this computer, sizeof(&main) is 8, sizeof(int) is 4.
- JoachimSchipper 16y agoFunction pointers are all kinds of iffy - you can't translate them to void *, for instance (this makes total sense if you consider the fact that C programs may run on embedded devices with separate RAM/ROM addressing schemes). I'm not sure about arithmetic, but I'd expect it to be undefined. If you do want to put a (non-function) pointer into an integer, convert to (C99) [u]intptr_t. Of course, that does not have to be defined...
- NickPollard 16y agoReally? I didn't know that. Shows how much I have still to learn about C. A program I'm writing now uses void* as a generic function pointer, which I cast to different function signatures as required depending on usage. I'm guessing that's considered harmful, is there a better or more idiomatic way to do this?
- kragen 16y agoI believe there is not a standard way to do what you are doing. However, in common implementations of C, you'll only have trouble if some of your functions have a different calling convention than others — stdcall, say, or fastcall, or Pascal calling convention, or far vs. near calls on 16-bit x86. I assume you can avoid that with a union with one member for each calling convention, but I've never tried it. Architectures where code pointers are bigger than data pointers are fairly exotic, I think. The AS/400 might be an example, I'm not sure. However! You can avoid that particular problem by using (void* )(void) as your generic function pointer type, rather than simply void *.
- JoachimSchipper 16y agoPretty much the only standard way to do this involves something like "void (fp)(void arg)" or "void (*fp)(va_list ap)" and generous casting. That said, this is not that likely to be a problem in practice on Unix machines (Windows has more than one calling convention - I have no idea how much of a problem that is.)
- caf 16y agoIt's guaranteed that function pointers survive a round-trip conversion to other function pointer types - so you can just use a type like `void (*fp)()` as a "generic" container, making sure that it's cast back to the correct type before use.
- nitrogen 16y agoI was about to point out that pointers are supposed to fit in intptr_t, but you're right -- there probably isn't a specification for function pointers (it's too late for me to feel like checking the spec). I will add, though, that on Linux on common 32- and 64-bit CPUs an unsigned long will always fit a pointer (excluding the possibility that ucLinux has been ported to a Harvard architecture or other "non-traditional" machine).