5 ms·
Sigh, if the program is relying on undefined behavior [like this one], it's not C. Plus, gcc has __builtin_apply as extension.
by zvrba 14y ago
Sigh, if the program is relying on undefined behavior [like this one], it's not C. Plus, gcc has __builtin_apply as extension.
- daeken 14y agoThis is not undefined behavior. It's implementation specific behavior -- there's a huge difference. If you specify the calling convention for your functions, this is 100% deterministic and predictable. Nothing at all wrong with this approach.
- zvrba 14y agoNot 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).
- daeken 14y agoAgain, 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.
- zvrba 14y ago> 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.
- to3m 14y ago6.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...
- zvrba 14y ago6.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).
- to3m 14y agoYes - 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.
- tedunangst 14y agoThe 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, ...).