Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!caip!rutgers!husc6!mit-eddie!genrad!decvax!tektronix!hplabs!pyramid!prls!philabs!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP Newsgroups: net.lang.c Subject: Re: Casting void - int question Message-ID: <651@dg_rtp.UUCP> Date: Sat, 18-Oct-86 13:57:37 EDT Article-I.D.: dg_rtp.651 Posted: Sat Oct 18 13:57:37 1986 Date-Received: Tue, 21-Oct-86 23:04:37 EDT References: <26@orion.UUCP> Lines: 65 Summary: cast of (int (*)()) should work on a (void (*)()) expression > heins@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 !mcnc!rti-sel!dg_rtp!throopw