[comp.unix.questions] Casting function ptrs

daveh@marob.MASA.COM (Dave Hammond) (05/19/88)

Given a list of varying typed functions, their names and addresses:

struct funcs {
    char *name;
    unsigned (*func)();
}
char *foo();
struct funcs f = {  "foo", (char *)foo };

And a routine which is passed a function name in order to lookup and return
its associated address: 

unsigned *lookup_func(name)
char *name;
{
  ...
  return( (unsigned *) f->func );
}

How does one declare the lookup function, the return address variable and
call the returned function, while properly casting the function return value?
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);
    }

Yes? No? Gonna blow up on me at some point ?


Dave Hammond
DSI Communications, Inc.
--------------------------------
UUCP:   ...!marob!daveh
VOICE:  (516)872-3535
USMAIL: 333 W. Merrick Rd.
        Valley Stream, NY 11580
--------------------------------

chris@mimsy.UUCP (Chris Torek) (05/19/88)

In article <280@marob.MASA.COM> daveh@marob.MASA.COM (Dave Hammond) asks
about variadic return-value functions and pointers thereto, a duplicate
of the same question he sent to comp.lang.c.  Look there for my answer.

(Incidentally, it is considered bad form to post the same question
separately to two newsgroups.  There *is* a reason for the second `s'
in `Newsgroups:'.  People on the mailing-list side of the ARPA/USENET
gateways are, of course, stuck with the bad form, or a more limited
forum.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

haugj@pigs.UUCP (John F. Haugh II) (05/21/88)

In article <280@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
> Given a list of varying typed functions, their names and addresses:
> 
> struct funcs {
>     char *name;
>     unsigned (*func)();
> }
> char *foo();
> struct funcs f = {  "foo", (char *)foo };


the field `func' is `pointer to function returning unsigned'.  assigning
anything else to it, such as a pointer to a function returning a pointer
to a character, as you do in the example above, is wrong.

> And a routine which is passed a function name in order to lookup and return
> its associated address: 
> 
> unsigned *lookup_func(name)
> char *name;
> {
>   ...
>   return( (unsigned *) f->func );
> }

this is also incorrect.  lookup_func should have its return value the same
type as f->func.  the correct declaraction for lookup_func is

unsigned *(*lookup_func()) (name)
char	*name;
{
	...
}

> How does one declare the lookup function, the return address variable and
> call the returned function, while properly casting the function return value?
> 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);
>     }

the return address variable has the same type as f->func, which is `pointer
to function returning pointer to unsigned', or

unsigned *(*retp) ();

> Yes? No? Gonna blow up on me at some point ?
>-- 
> Dave Hammond

the people at ANSI land will tell you can't go converting between different
types of pointers and expecting ``reasonable'' results.  so, yes, it will
blow up on you at some point.

i suggest you find a copy of the `cdecl' program.  it can come in very
handy for writing casts and function and variable declarations.  it also
comes in handy for writing USENET articles ;-)

- john.
-- 
 The Beach Bum                                 Big "D" Home for Wayward Hackers
 UUCP: ...!killer!rpp386!jfh                          jfh@rpp386.uucp :SMAILERS

 "You are in a twisty little maze of UUCP connections, all alike" -- fortune

mouse@mcgill-vision.UUCP (der Mouse) (05/30/88)

In article <127@pigs.UUCP>, haugj@pigs.UUCP (John F. Haugh II) writes:
> In article <280@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes:
>> Given a list of varying typed functions, their names and addresses:
>> struct funcs { char *name; unsigned (*func)(); };
>> char *foo();
>> struct funcs f = {  "foo", (char *)foo };
> the field `func' is `pointer to function returning unsigned'.
> assigning anything else to it, such as a pointer to a function
> returning a pointer to a character, as you do in the example above,
> is wrong.

Except that what he's assigning is not a pointer to function at all,
but a pointer to char (as per the cast).  Try

struct funcs f = { "foo", (unsigned (*)())foo };

>> And a routine which is passed a function name in order to lookup and
>> return its associated address:
>> unsigned *lookup_func(name) char *name;
>> { .... return( (unsigned *) f->func ); }
> this is also incorrect.  lookup_func should have its return value the
> same type as f->func.

Yes.

> the correct declaraction for lookup_func is
> unsigned *(*lookup_func()) (name) char *name; { ... }

This declares lookup_func as a function with no arguments returning a
pointer to a function returning pointer to unsigned.  The "char *name"
will provoke an error message about an argument declared but not
mentioned in the argument list.  The place you have name is the
argument list for the *return value*, not for lookup_func itself; this
will likely provoke another error message unless your compiler accepts
ANSI-style prototype argument lists (and possibly then; I'm not certain
whether the above is legal ANSI, or rather would be if the "char *name"
were deleted).

Try

unsigned (*lookup_func(name))()
char *name;
{
 unsigned (*retp)();
 ...
 return(retp);
}

If your compiler accepts ANSI-style prototype argument lists, you can
put stuff in the other pairs of parentheses to declare the arguments to
the return value:

unsigned (*lookup_func(char *name))(int,int,long)
/* for example.  Returned function takes three args: int, int, and long. */
{
 unsigned (*retp)(int,int,long);
 ....
 retp = (unsigned (*)(int,int,long)) ....;
 ....
 return(retp);
}

					der Mouse

			uucp: mouse@mcgill-vision.uucp
			arpa: mouse@larry.mcrcim.mcgill.edu