[comp.unix.programmer] Recasting to a pointer to a function.

elston@edwards-saftd-2.af.mil (03/15/91)

We are trying to assign to a pointer to a function the value stored in a
long (which on our system is the same size.)  We would like to recast the long
into a function pointer.  Is there any method for doing this in 'C'?
We tried the following


   int (*dbp)();
   long lvar;
   .
   .
   .
   dbp = (()*) lvar;

and it failed to compile.  Is there any method for doing this recast?  The
other option we have tried is

   (long) dbp = lvar;

but when we run this we get a core dump (at the minimum).  We are not sure if
this is due to improper handling of the recast (should not be) or ?????
Does anyone have any ideas?

Thanks in advance,

Mark
-- 
##############################################################################
# A mind is a terrible thing to waste -      elston@edwards-saftd-2.af.mil   #
#     Thank goodness mine's all used up.                                     #
#                                                                            #
# If the author has expressed any opinions here they are purely              #
#  accidental and should be ignored.                                         #
##############################################################################

aryeh@eddie.mit.edu (Aryeh M. Weiss) (03/16/91)

In article <1991Mar14.155825.31@edwards-saftd-2.af.mil> elston@edwards-saftd-2.af.mil writes:
>We are trying to assign to a pointer to a function the value stored in a
>long (which on our system is the same size.)  We would like to recast the long
>into a function pointer.  Is there any method for doing this in 'C'?
>We tried the following

The ``proper'' way is not to do it at all, but rewrite your app into
a portable form, or to use a union like
	union { long x; (int *p)(); } temp;
but you already know that.

The correct form of the cast is

	dbp = (int (*)()) lvar;

jim@segue.segue.com (Jim Balter) (03/17/91)

In article <1991Mar14.155825.31@edwards-saftd-2.af.mil> elston@edwards-saftd-2.af.mil writes:
>   int (*dbp)();
>   long lvar;
>   .
>   .
>   .
>   dbp = (()*) lvar;

I can't imagine why you would think that random collection of characters
would constitute a valid cast, let alone the one you want.

Contrary to popular opinion, C types are easy if you follow some simple rules.
The basic rule for casts is to put the declaration in parentheses and then
drop the name.   This yields

    dbp = (int (*)()) lvar;

Or, use typedefs:

    typedef	int	(*ifunc_t)();
    ifunc_t	dbp;

    dbp = (ifunc_t)lvar;

>   (long) dbp = lvar;
>
>but when we run this we get a core dump (at the minimum).

A core dump from the compiler, or from the compiled program?  Your compiler
is sick if it lets that pass without an error message.   Where did you find
in TFCM that you can cast the expression on the left side of the assignment?
Read about lvalues.  If you really wanted to do it that way (you don't), try

#define LVALUE_CAST(var, type) *(type *)&(var)	/* var can't be register */

    LVALUE_CAST(dbp, long) = lvar;

Finally, all of this is non-portable and error-prone.  Casts hide warnings,
and if you use ANSI prototypes they are almost never needed.
If you need a generic type that can hold longs, function ptrs, etc.,
lvar should have a union type.  Try

    typedef union {
	long	l;
	int	(*ifunc)(); /* for strict ANSI, include the types of the
			       parameters and a separate type in the union for
			       each different set of function parameter and
			       return types */
    } gen_t;

    gen_t gvar;
    int   (*dbp)();	    /* for ANSI, include parameter types */
    .
    .
    .
    dbp = gvar.ifunc;