[comp.lang.c] Recasting to a pointer to a function.

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;