typedef int (*mock_func_ptr)();
typedef mock_func_ptr (*daisychain_func_ptr)();
daisychain_func_ptr
me(daisychain_func_ptr new_func)
{
daisychain_func_ptr next;
int call_me_again;
/* do something useful here...*/
if (call_me_again) {
if (!next) {
next = (daisychain_func_ptr)new_func(0);
}
else {
next = (daisychain_func_ptr)next(new_func);
}
return (daisychain_func_ptr)me;
}
else {
if (next) {
daisychain_func_ptr t = next;
next = 0;
return (daisychain_func_ptr)t(new_func);
}
else if (new_func) {
return (daisychain_func_ptr)new_func(0);
}
else {
return 0;
}
}
}
After having some spare minutes to think about it while driving home,
I think I can answer myself: the above IS undefined behaviour because
the function pointers are deref'd with the wrong type. I should have
noticed when I had to cast the "me" in the return statement.
I think you can avoid the undefined behavior by using void pointers
as intermediaries. I'm not sure what this is supposed to "do", but
I think the following is equivalent to your example.
HTH!
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
void * me (void *vfunc) {
static void *(*next)(void *) = NULL;
static bool again = false;
void *(*func)(void *) = vfunc;
if (again) {
return next = next?next(func):func(NULL);
} else {
if (next) {
void *(*t)(void *) = next;
next = NULL;
return t(func);
} else if (func) {
return func(NULL);
} else return NULL;
}
}
int main() {
printf("%x\n", me(NULL));
printf("%x\n", me(me));
}
--
lxt
That won't generally work. void * can't be relied on to be able to
store a function pointer.
The standard appears to disagree.
J.5.7 Function pointer casts
A pointer to an object or to void may be cast to a pointer to a
function, allowing data to
be invoked as a function (6.5.4).
A pointer to a function may be cast to a pointer to an object or to
void, allowing a
function to be inspected or modified (for example, by a debugger)
(6.5.4).
--
lxt
Now read the heading of Appendix J. It is "Common Extensions". So the
standard is telling you that this is a common extension and *not*
something specifically allowed.
--
Flash Gordon
Annex J is non normative. J.5 is Common extensions.
--
Peter
Annex J.5 is entitled "Common extensions". These are features that some
implementations provide, but they are not required to do so.
More to the point here is 6.3.2.3 (1). "A pointer to void may be
converted to or from a pointer to any incomplete or object type."
Function types are not included, and AFAIK there is nowhere else in the
body of the Standard that allows converting a function pointer to and
from a void pointer.
Section J.5 is titled "Common extensions.
I'll just assume that "The standard appears to disagree." wasn't meant
to imply that it actually does disagree.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Yes. It was the first thing I found so I rushed off to retort.
The statement was intentionally vague to reflect my lack of
certainty. Correction appreciated.
--
lxt