6 ms·
... without conditionals. Cute puzzle, nice to see some inventive torturing of C, and various dialects that people believe are C.
by RiderOfGiraffes 16y ago
... without conditionals.
Cute puzzle, nice to see some inventive torturing of C, and various dialects that people believe are C.
- chops 16y agoand various dialects that people believe are C. To be fair, the SO question specifies "using C or C++", not just C.
- RiderOfGiraffes 16y agoTrue. At a glance I'm suspicious that some might truly be in neither, but I'm not really bothered to check. Any Language Lawyers around?
- nathanb 16y agoWithout specifying dialect (ANSI C, C99, etc.), I believe "valid C" really only means "some C compiler somewhere will accept it without generating errors".
- TillE 16y agoSomeone claims the second answer "obviously" isn't C, which I don't understand. GCC 4.5.2 compiles it without complaint. Is pointer arithmetic not allowed? Or calling main()?
- tspiteri 16y agoI'm not sure pointer arithmetic on function pointers is standard C. Using the -pedantic flag, gcc 4.5.2 does give a "warning: pointer to a function used in subtraction".
- emillon 16y agoThe paragraph on pointer differences (ANSI C99 6.5.6§9) states that : "both shall point to elements of the same array object, or one past the last element of the array object […] The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t". So, for an array of function pointer that would be legal behaviour, but for pointers to plain functions, it is undefined behaviour.
- nitrogen 16y agoWhen I was in high school I thought I could implement shared libraries for DOS/DJGPP by subtracting function pointers to each function I wanted to export and dumping the intervening data to disk. I quickly realized that the code was not position independent, and that other segments (like strings) were not being exported. I also discovered Linux, and thus abandoned the idea.
- silentbicycle 16y agoIt 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.)
- acqq 16y agoSubtracting function pointers doesn't have to have any meaning. Tiny C (from 2006, 5 years old) gives: function pointer expected MS C 6 (from 1998, 13 years old) gives error C2296: '-' : illegal, left operand has type 'void (__cdecl *)(int )' Turbo C 2.01 (from 1988, 23 years old) gives: Size of structure or array not known in function etc. I think the really clean solution (as far as I know, at least it works with all the compilers I've mentioned) is: http://news.ycombinator.com/item?id=2323771 http://news.ycombinator.com/item?id=2323771
- derleth 16y agoAnything that has 'void main' isn't quite up to snuff, to begin with.
- ctdonath 16y ago"nice to see some inventive torturing of C" What ever happened to the IOCCC? (International Obfuscated C Coding Contest, ioccc.org)