Casting function ptrs
Chris Torek
chris at mimsy.UUCP
Fri May 20 00:16:47 AEST 1988
In article <281 at marob.MASA.COM> daveh at marob.MASA.COM (Dave Hammond) writes:
>Given a list of varying typed functions,
Danger Will Robinson :-)
`Varying typed' should trigger alarm bells.
>their names and addresses ... and a routine which is passed a function
>name in order to lookup and return its associated address ...
>How does one declare the lookup function, the return address variable and
>call the returned function, while properly casting the function return value?
Depending on the type variation, there may not be a `proper cast'.
Some types may be mixed (e.g., pointers, via `void *' per the dpANS,
or integral types, via the longest of the bunch). If there is no
common type, you must use a union:
/* function-pointer union */
union fpu { /* abbreviation `f.u.' avoided for obvious reasons :-) */
long (*ifn)(void); /* for integral functions */
double (*fn)(void); /* for floating functions */
void *(*ptrfn)(void);/* for object-pointer functions */
void (*(*codefn)())();/* for code-pointer functions */
void *(*(*pcfn)())();/* for ptr valued code-ptr fns */
/* &c ad nauseam */
};
struct ftable {
char *name; /* the function's name */
int type; /* its return type */
union fpu fn; /* and its address */
};
Alas, you cannot initialise a union except via its first member,
and that only in dpANS-conformant compilers.
Assuming that all the functions return pointers, you can resort to
this (dropping the prototypes):
typedef void *PTR; /* or char *, if void * fails */
/* optional: */
typedef PTR (*PFP)(); /* ptr to function returning generic ptr */
unsigned *a();
char *b();
double *c();
enum ftype { F_UNSIGNED, F_CHAR, F_DOUBLE };
struct ftable {
char *name;
enum ftype ftype;
PTR (*fn)(); /* or PFP fn */
} ftable[] = {
"a", F_UNSIGNED, (PTR (*)())a, /* or (PFP)a */
"b", F_CHAR, (PTR (*)())b, /* etc */
"c", F_DOUBLE, (PTR (*)())c
0
};
>I'm doing it like so:
>
>unsigned *lookup_func();
>unsigned *(*func)();
>char *retp;
>
>if ((func = lookup_func("foo")) != (unsigned *)0) {
> if (( retp = (char *) (*func)() ))
> printf("retp=%s",retp);
> }
Try
/* clearest: */
PFP lookup_func();
/* expanded one level: */
/* PTR (*lookup_func())(); */
/* whole hog: */
/* void *(*lookup_func())(); */
PFP func;
char *retp;
/* also make sure we get the right type back: */
if ((func = lookup_func("foo", F_CHAR)) != NULL)
if ((retp = (char *)(*func)()) != NULL)
printf("retp=%s", retp);
One might wonder, given the less clear `lookup_func' declarations
above, where the arguments go:
void *(*lookup_func(name, type))()
char *name;
enum ftype type;
{
register struct ftable *p;
for (p = ftable; p->name != NULL; p++) {
if (p->ftype != type)
continue;
if (strcmp(p->name, name) == 0)
return (p->fn);
}
return (NULL);
}
It is rather simpler to write
PFP lookup_func(name, type)
char *name;
enum ftype type;
{ ...
as I think everyone will agree :-) .
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.lang.c
mailing list