[comp.lang.c] How do I cast to "pointer to function returning int" ?

drh@romeo.cs.duke.edu (D. Richard Hipp) (04/10/90)

In article <6090.2621f6c2@csv.viccol.edu.au> timcc@csv.viccol.edu.au writes:
>struct foo {
>   char *name ;
>   int (*function) () ;
>   } ;
>
>struct foo foo_table[] = {
>   "bar",	(int * ()) bar,
>   "blurfl",	(int * ()) blurfl,
>   "frobjitz",	(int * ()) frobjitz,
>   } ;

The typecast (int *()) is for "function returning pointer to integer".
To get "pointer to function returning integer" use (int (*)()).

The rule is this: operators on the right hand side bind tighter than
operators on the left hand side.  Thus "()" binds tighter than "*".
You want the "*" to bind closest, so the extra parenthesis are required.

timcc@csv.viccol.edu.au (04/11/90)

Given the following C source:

extern void bar () ;
extern void blurfl () ;
extern void frobjitz () ;

struct foo {
   char *name ;
   int (*function) () ;
   } ;

struct foo foo_table[] = {
   "bar",	(int * ()) bar,
   "blurfl",	(int * ()) blurfl,
   "frobjitz",	(int * ()) frobjitz,
   } ;

I get the following errors from GNU C, version 1.36:

above_source:11: conversion to non-scalar type requested
above_source:12: conversion to non-scalar type requested
above_source:13: conversion to non-scalar type requested

So how do I cast to "pointer to function returning int" ?
--
Tim Cook     Systems Administrator, Victoria College Computer Services

parrot - n.  An animal that has the ability to imitate man, but not the
             intelligence to refrain from doing so.

CMH117@psuvm.psu.edu (Charles Hannum) (04/11/90)

In article <6090.2621f6c2@csv.viccol.edu.au>, timcc@csv.viccol.edu.au says:
>
>So how do I cast to "pointer to function returning int" ?

Get yourself a copy of cdecl.  Then:

   cdecl
   Type "help" or "?" for help.
   cdecl> cast foo into pointer to function returning int
   (int (*)())foo
   cdecl> quit

IMHO, anyone who doesn't use cdecl is crazy.

BTW:  Casting a void function to an int function is extremely non-portable.


Virtually,
- Charles Martin Hannum II       "Klein bottle for sale ... inquire within."
    (That's Charles to you!)     "To life immortal!"
  cmh117@psuvm.{bitnet,psu.edu}  "No noozzzz izzz netzzzsnoozzzzz..."
  c9h@psuecl.{bitnet,psu.edu}    "Mem'ry, all alone in the moonlight ..."

martin@mwtech.UUCP (Martin Weitzel) (04/11/90)

In article <18834@duke.cs.duke.edu> drh@romeo.UUCP (D. Richard Hipp) writes:
:In article <6090.2621f6c2@csv.viccol.edu.au> timcc@csv.viccol.edu.au writes:
:>struct foo {
:>   char *name ;
:>   int (*function) () ;
:>   } ;
:>
:>struct foo foo_table[] = {
:>   "bar",	(int * ()) bar,
:>   "blurfl",	(int * ()) blurfl,
:>   "frobjitz",	(int * ()) frobjitz,
:>   } ;
:
:The typecast (int *()) is for "function returning pointer to integer".
:To get "pointer to function returning integer" use (int (*)()).
:
:The rule is this: operators on the right hand side bind tighter than
:operators on the left hand side.  Thus "()" binds tighter than "*".
:You want the "*" to bind closest, so the extra parenthesis are required.

Or, if you want an easy 'step-to-step' procedure, do it as follows:

	1) write a declaration for some object 'foo', so that
	   'foo' has the desired type.
	2) avoid all unnecessary brackets (here the above
	   rule comes into play, that '()' and '[]' on the right
	   bind more tightly than '*' on the left; use brackets
	   like in expressions, if you want other binding)
	3) cancel the name 'foo' and enclose what remains
	   in brackets
	4) after half an hour take the freshly baked cast
	   out of the oven and enjoy!
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

martin@mwtech.UUCP (Martin Weitzel) (04/11/90)

In article <90100.172535CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes:
[some lines deleted]
>
>IMHO, anyone who doesn't use cdecl is crazy.

very small flame (no, not really a flame)

IMHO, better try to *understand* how it must be done.

Before the age of electronic pocket calculators (oh, can you imangine,
these little things were not allways around since God created the
world), people used to know that, say 12.5 percent from $18.60 must be
roughly around $2.00 - today they happily use their pocket calculator
and will accept every answer between $0.02 (the smallest coin in
their cash register) or $200.00 (because that's the maximum amount,
they are allowed to pay to you without notifying their boss).

Just a story, ehhm, yes kkkkeys bounce somettttimes.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

williamt@athena1.Sun.COM (William A. Turnbow) (04/11/90)

	Where can one get a copy of cdecl?
-wat-

   --- An it harm none, do what you will.
*** America vs. developed country rankings: chemistry 11/13, physics 9/13
    biology 13/13, infant mortality 1/13, teen pregnancy 1/13

cml@tove.umd.edu (Christopher Lott) (04/11/90)

In article <134288@sun.Eng.Sun.COM> williamt@sun.UUCP (William A. Turnbow) writes:
>	Where can one get a copy of cdecl?

I posted this info about a month ago.  Brief recap:

cdecl is available for anonymous ftp from mimsy.umd.edu as "cdecl.shar"

The local name server tells me this about mimsy:
	mimsy.umd.edu   432000 IN       A       128.8.128.8

Desperate uucp sites can email me for a copy.

chris...
--
cml@tove.umd.edu    Dept. of Computer Science, U. Maryland at College Park
		    4122 A.V.Williams  301-454-8711 <standard disclaimers>

mcdaniel@amara.uucp (Tim McDaniel) (04/13/90)

CMH117@psuvm.psu.edu (Charles Hannum) writes:
   Casting a void function to an int function is extremely non-portable.

Not quite.  ANSI C, and many existing compilers, requires that
function pointers all be the same size.  Any pointer to a function can
be cast into any other pointer-to-function type and back again,
producing the same pointer value.  However, the value can't be called
while it is cast to a different type.  For example:

   typedef anytype   (*PF_ANY  )();
   typedef othertype (*PF_OTHER)();
   /*
    * PF_ANY is the type "pointer to function () returning anytype".
    * PF_OTHER is the type "pointer to function () returning othertype".
    * Assume that anytype and othertype are different types.
    */
   PF_ANY   f1, f2;
   PF_OTHER g;
   ...
   g  = (PF_OTHER) f1;	  /* legal under ANSI C */
   f2 = (PF_ANY) g;	  /* legal under ANSI C */
   if (f1 != f2) {
      /* then this compiler is not ANSI C compliant. */
      }
   (*f2)();		  /* exact same result as "(*f1)();" */
   (*g)();		  /* illegal under ANSI C */

And, by the way,
   f2 = (PF_ANY) (void *) f1;
is illegal in ANSI C.  "void *" is the universal pointer only for DATA
objects, not functions.  You can convert any FUNCTION pointer to any
other FUNCTION pointer type.

To rephrase, then:
   Casting a pointer to void function to a pointer to int function
   type, and calling that result, is extremely non-portable.

--
Tim McDaniel
Applied Dynamics International, Ann Arbor, MI
Internet: mcdaniel%amara.uucp@mailgw.cc.umich.edu
UUCP: {uunet,sharkey}!amara!mcdaniel