Casting void - int question

throopw at dg_rtp.UUCP throopw at dg_rtp.UUCP
Sun Oct 19 03:57:37 AEST 1986


> heins at orion.UUCP (Michael T. Heins)
> My problem is that the compiler complains about incompatible types, and
> I can't figure out how to use casts or unions to solve the problem.

Well, the cast solution you gave ought to have worked.  And, indeed, it
works for the compiler and lint that I use.  The draft ANSI C document
has this to say, in 3.3.4:

    A pointer to a function of one type may be converted to a pointer to
    a function of another type and back again; the result shall compare
    equal to the original pointer.  If a converted pointer is used to
    call a function of other than the original type, the behavior is
    undefined.

So, the good news is that draft ANSI says the cast must work.  On the
other hand, the bad news is that you can't portably use the cast pointer
to invoke the function.  Sigh.

On the third hand, almost all extant C compilers (which support the
relevant types) will work correctly when a pointer expression of type
(int (*)()) is used to invoke a function of type (void ()).  On the
fourth hand (look, ma! four hands!), if you *really* want to be
portable, you might should do something like this:

    /* to declare the array of functions to call */
    typedef union { void (*v)(); int (*i)();} func_ptr_t;
    typedef enum {void_func, int_func} func_kind_t;
    typedef struct { func_kind_t kind; func_ptr_t ptr; } func_desc_t;
    func_desc_t func_desc[N];

    /* to install a new function */
    switch(func_kind){
    case(void_func): func_desc[i].ptr.v = some_void_func; break;
    case(int_func):  func_desc[i].ptr.i = some_int_func;  break;
    }
    func_desc[i].kind = func_kind;

    /* to invoke a function */
    switch(func_desc[i].kind){
    case(void_func): (*func_desc[i].ptr.v)(); break;
    case(int_func):  (*func_desc[i].ptr.i)(); break;
    }

OK, OK, so it's ugly *ugly* *UGLY*!!!  On the other hand, it is the
simplest portable method I've come up with that does the job and
directly invokes the function.  It is also possible to do it a more
flexible way which trades an extra function invocation for the switch at
invocation time (and which can be expanded to invoke more types of
functions without changing the invocation code).  This method isn't
really any simpler in its general form, and is left as an excersize for
the masochistic reader.

--
Like punning, programming is a play on words.
                                --- Alan J. Perlis
--
(By the way, "might should" (along with "might could" and other
might-modified forms) is a feature of the local dialect that I threw in
there on purpose for whimsical effect.  I did realize it isn't quite
correct when I did it.  Really.  No, wait, I really *did* do it on
purpose!  Where's everybody going?  Don't you believe me?  You can't
just walk out on me like this!!  COME BACK!  WAIT... oh, what's the
use?  At least I linted my examples... hmpf!)
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw



More information about the Comp.lang.c mailing list