[comp.lang.c] function casting

clark@umn-cs.CS.UMN.EDU (Robert P. Clark) (04/30/89)

How do I cast something to a pointer to a function that returns
an integer?  I'm trying to save the old function, so that I can
call my own function and then chain to the original.


One of my (failed) attempts has been


main()
{
  int  (*f)();
  char *foo();


    f = ((*int)())foo();  /*  foo returns char*, but I know this is  */
                          /*  really an address of a function        */
}




                     Bob Clark        clark@umn-cs.cs.umn.edu

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ~                                                       ~
    ~          Never underestimate the bandwidth of         ~
    ~          a station wagon  - Andrew Tannenbaum         ~
    ~                                                       ~
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mcgrath@paris.Berkeley.EDU (Roland McGrath) (04/30/89)

int (*f)();
char *foo();

f = (int (*)()) foo();
--
	Roland McGrath
	Free Software Foundation, Inc.
roland@wheaties.ai.mit.edu, mit-eddie!wheaties.ai.mit.edu!roland
Copyright 1989 Roland McGrath, under the GNU General Public License, version 1.

bph@buengc.BU.EDU (Blair P. Houghton) (04/30/89)

In article <12481@umn-cs.CS.UMN.EDU> clark@umn-cs.CS.UMN.EDU (Robert P. Clark) writes:
>
>main()
>{
>  int  (*f)();

It's alright, so far...

>  char *foo();
>
>
>    f = ((*int)())foo();  /*  foo returns char*, but I know this is  */
>                          /*  really an address of a function        */

Bad declaration-to-cast conversion...

You want merely to remove the identifier when doing a cast, rather
that rearranging anything.

The declaration

   int (*f)();

becomes a cast, therefore, by excising the "f" and the ";" and
pre-/ap-pending "(" and ")".

   f = ( int (*)() ) foo();

>}

There are programs out there that do it.

If you really want to know, by doing

   f = ((*int)())...

You're trying to call a function pointed-to by a thing called 'int'
which is a C keyword, and therefore will generate all sorts of syntactical
trouble in the situation you've placed it.

PLUG ALERT!

Andrew Koenig's _C Traps and Pitfalls_ handles this about as well
as it can be handled...

GO BACK TO YOUR HOMES, THERE'S NOTHING LEFT TO BE BOUGHT, HERE...

				--Blair
				  "Do I get a free copy of
				   ed. 2, now, huh, Andy, huh,
				   do I do I do I ??  :-)"

ark@alice.UUCP (Andrew Koenig) (04/30/89)

In article <12481@umn-cs.CS.UMN.EDU>, clark@umn-cs.CS.UMN.EDU (Robert P. Clark) writes:

> How do I cast something to a pointer to a function that returns
> an integer? One of my (failed) attempts has been


> main()
> {
>   int  (*f)();
>   char *foo();


>     f = ((*int)())foo();  /*  foo returns char*, but I know this is  */

> }

Best would be to make foo return an appropriate pointer ane
avoid type cheating:

	int (*foo())();
	int (*f)();

	f = foo();

The declaration of foo here says that if you call foo, dereference the
result, and call that, you get an int.  The definition of foo would
look something like this:

	int (*foo())()
	{
		/* ... */
	}

Don't be too astonished if your compiler balks at this -- but
it is indeed valid C.

Next question: how to declare a variable to contain a pointer to
a function that returns an integer?  If f is such a variable,
then to get an integer from it, you dereference it (to get a
function from the function pointer) and then call the function.
As your example shows, such a declaration looks like this:

	int (*f)();

Finally, how do you cast a value to the type of f, assuming
you still want to?  A cast looks a lot like the declaration
with parentheses around it, and with the variable removed
that was declared.  So int(*f)() becomes (int(*)()) and the
assignment looks something like this:

	f = (int(*)()) foo();

Of course, the cast is unnecessary if you get the type of
foo right to begin with.  [C-T&P, p. 13]
-- 
				--Andrew Koenig
				  ark@europa.att.com

geoff@cs.warwick.ac.uk (Geoff Rimmer) (05/01/89)

In article <12481@umn-cs.CS.UMN.EDU> clark@umn-cs.CS.UMN.EDU (Robert P. Clark) writes:

> How do I cast something to a pointer to a function that returns
> an integer?  

The way I use is to imagine I am defining a variable x to be a pointer
to function returning int.  I would use:

	int (*x)();

To change this into a cast, take out the x, and put the whole lot in
parentheses.

	(int (*)())

Get the cdecl program!  It will do all of this for you.

Hope this helps.
Geoff

	/---------------------------------------------------------------\
	|	GEOFF RIMMER  - Friend of fax booths, ANSI C, PCBH,	|
	|			& MPFC & cdecl				|
	|	email	: geoff@uk.ac.warwick.emerald			|
	|	address : Computer Science Dept, Warwick University, 	|
	|		  Coventry, England.				|
	|	PHONE	: +44 203 692320 (10 lines) If I'm out please	|
	|			   leave a message with my secretary.	|
	|	FAX	: +44 865 726753				|
	\---------------------------------------------------------------/

byron@pyr.gatech.EDU (Byron A Jeff) (05/01/89)

In article <12481@umn-cs.CS.UMN.EDU> clark@umn-cs.CS.UMN.EDU (Robert P. Clark) writes:
-
-How do I cast something to a pointer to a function that returns
-an integer?  I'm trying to save the old function, so that I can
-call my own function and then chain to the original.
-
-
-One of my (failed) attempts has been
-
-
-main()
-{
-  int  (*f)();
-  char *foo();
-
-
-    f = ((*int)())foo();  /*  foo returns char*, but I know this is  */
-                          /*  really an address of a function        */
-}
-
-
-
Try this:
     f = (int (*)()) foo();

Because of the parens around the * it is interpreted first. It reads
"cast to a pointer to a function that returns int".

A simple rule of thumb I just though of for doing this: Use
exactly the same declaration for the variable you're trying
to cast to but remove the name (and of course put an extra set
of parens around it.)

So int (*f)() becomes (int (*)()). Yes?

Also it's best to make foo return the same type as
f unless there's a real good reason not to (IMHO).

BAJ
-
-                     Bob Clark        clark@umn-cs.cs.umn.edu
-- 
Another random extraction from the mental bit stream of...
Byron A. Jeff
Georgia Tech, Atlanta GA 30332
Internet:	byron@pyr.gatech.edu  uucp:	...!gatech!pyr!byron

diamond@diamond.csl.sony.junet (Norman Diamond) (05/02/89)

In article <12481@umn-cs.CS.UMN.EDU>, clark@umn-cs.CS.UMN.EDU (Robert P. Clark) writes:

>> How do I cast something to a pointer to a function that returns
>> an integer?

In article <9266@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:

>Best would be to make foo return an appropriate pointer ane
>avoid type cheating:
>
>	int (*foo())();
>	int (*f)();
>
>	f = foo();
>
>The declaration of foo here says that if you call foo, dereference the
>result, and call that, you get an int.  The definition of foo would
>look something like this:
>
>	int (*foo())()
>	{
>		/* ... */
>	}
>
>Don't be too astonished if your compiler balks at this -- but
>it is indeed valid C.

Mr. Koenig's answers are 100% correct.  However, the use of typedef
might solve the problem of broken compilers, and maybe even the
problem of broken co-workers who have to read your code:

typedef int                   purpose_of_f_t();
typedef purpose_of_f_t       *purpose_of_f_ptr_t;
typedef purpose_of_f_ptr_t    purpose_of_foo_t();

purpose_of_foo_t              foo;
purpose_of_f_ptr_t            f_ptr;
int                           my_int;

    /* ... */
    f_ptr = foo();
    /* ... */
    my_int = (*f_ptr)();

purpose_of_foo_t foo()
{
    /* ... */
}


Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
  The above opinions are my own.   |  Why are programmers criticized for
  If they're also your opinions,   |  re-inventing the wheel, when car
  you're infringing my copyright.  |  manufacturers are praised for it?