Not undefined behavior, really? Run it on a 64-bit SPARC system and see if it works. Not to mention that this implementation is dog-slow (two rather slow syscalls [mmap/munmap] for each apply-invocation).
Again, you're conflating undefined behavior with implementation-specific behavior. By your definition, anything that does implementation-specific typedefs, uses inline assembly, or even makes syscalls is taking advantage of undefined behavior. That's silly and ignores the actual definition.
> Again, you're conflating undefined behavior with implementation-specific behavior.
No, I'm not. Casting between data and function pointers (or even a function pointer to a function pointer of different signature!) is undefined behavior. Look up the C spec.
6.3.2.3.8 - "A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer."
6.5.9.6 confirms that two function pointers that compare equal point to the same function.
From my careful study of the code, I have a nagging sensation that this might not quite be the end of the story as far as portability goes...
6.3.2.3.7 allows for conversion between pointers to data ("objects") and 6.3.2.3.8 allows for conversion between pointers to functions; there is no provision for casting between data and function pointers.
6.3.2.3.5 and .6 allow for abritrary (implementation-defined) conversions between integer types and pointer types, so any conversion between function and data pointers must go through a suitably large integer type if such exists (converting a function pointer to a too small integer type is UB).
Yes - my response is to the suggestion that casting between pointers to functions of different signature is undefined. I took this to be a suggestion that the part of the approach that involves having a general-purpose function that can accept a pointer to any kind of function, and reliably use that pointer (after it's been casted, if necessary) to get a pointer to the function in question, is fundamentally non-portable.
I remain unconvinced that this is a serious issue, all things considered. The odd feeling that there could be other roadblocks to a fully portable implementation still remains. Nevertheless, it appears that this particular part could actually be done portably.
The words inline assembly don't even exist in the C standard. Of course it's undefined. The standard specifically mentions a select finite list of behaviors which may be implementation defined (ones complement, twos complement, ...).