hpa@casbah.acns.nwu.edu (Peter Anvin) (01/24/91)
Hello everyone. Could someone please tell me if this is illegal in ANSI C, or if only Turbo C++ is picky: void foo(int p1, double p2, void (*zoom)(int x, double y)) { printf("Do something with %d and %ld\n",p1,p2); zoom(p1,p2); } int bar(int baz, double quux) { printf("Zooming... %lf\n",quux); return baz; } main() { foo(7,3.141592653938789,bar); /* Turbo C++ gives hard error here */ return 0; } Turbo C++ always terminates with a hard "Type mismatch" error. Is this correct behaviour, and if so, is there a way to declare a pointer to a function returning *anything or void* but still specify its parameters? Grateful for answer. /Peter P.S. I haven't been able to figure out... is X3J11 ANSI C *finalized* (ANSI C-90) or are we still muddling around with working drafts? -- H. Peter Anvin +++ A Strange Stranger +++ N9ITP/SM4TKN +++ INTERNET: hpa@casbah.acns.nwu.edu FIDONET: 1:115/989.4 BITNET: HPA@NUACC RBBSNET: 8:970/101.4
sarroyo@govtdev-11w9.shearson.com (Suzanne Arroyo) (01/25/91)
In article <2887@casbah.acns.nwu.edu> hpa@casbah.acns.nwu.edu (Peter Anvin) writes: > Turbo C++ always terminates with a hard "Type mismatch" error. Is this > correct behavior.....? Yes! Function foo was defined as: void foo ( int p1, double p2, void ( *zoom)(int x, double y)) ie, taking three parameters: an int, a double, and a *pointer to a function returning void** foo was called later with a pointer to a function returning *int* - causing the obvious type mismatch > is there a way to declare a pointer to a function returning *anything or void* but > still specify its parameters? A function must be declared with a single type - if you want it to be a catch-all type, then void is your choice - the problem there is passing the right type function pointer this works, but is messy: foo ( 7, 3.131592653938789, (void(*)(int, double) )bar); hope this helps -- Suzanne Arroyo Wusses Are Fun People!!!! Internet: sarroyo@govtdev-11w9.shearson.com UUCP: ...!uunet!slcpi!sarroyo
barmar@think.com (Barry Margolin) (01/25/91)
In article <SARROYO.91Jan24120512@govtdev-11w9.shearson.com> sarroyo@govtdev-11w9.shearson.com (Suzanne Arroyo) writes: [Regarding passing an int(*)() to a function expecting a void(*)()] >this works, but is messy: > foo ( 7, 3.131592653938789, (void(*)(int, double) )bar); Is this actually guaranteed to work right? What if the implementation uses a different calling sequence for a function returning void from one returning int? For instance, the space for a return value might be allocated by the caller. Is this allowed (I know they are allowed to use different calling sequences for varargs functions, but is the return type also allowed to influence the calling sequence)? If so, then foo won't call bar properly. -- Barry Margolin, Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar
browns@iccgcc.decnet.ab.com (Stan Brown) (01/25/91)
In article <2887@casbah.acns.nwu.edu>, hpa@casbah.acns.nwu.edu (Peter Anvin) writes: > > void foo(int p1, double p2, void (*zoom)(int x, double y)) So the third argument to 'foo' will be [the name of] a function that does not return a value. > int bar(int baz, double quux) Function 'bar' returns an int. > foo(7,3.141592653938789,bar); /* Turbo C++ gives hard error here */ But when you called 'foo' you gave it an int function as third argument. Returning something is not the same as returning nothing. > Turbo C++ always terminates with a hard "Type mismatch" error. Is this As it should, IMHO. > correct behaviour, and if so, is there a way to declare a pointer to a > function returning *anything or void* but still specify its parameters? I'm 99% sure the answer is No. A thing is not the same as nothing. Hey--this is all my opinion, nobody else's. Rely on it at your peril. email: browns@ab.com -or- browns@iccgcc.decnet.ab.com Stan Brown, Oak Road Systems, Cleveland, Ohio, USA +1 216 371 0043
scjones@thor.UUCP (Larry Jones) (01/26/91)
In article <1991Jan24.181041.4894@Think.COM>, barmar@think.com (Barry Margolin) writes: > In article <SARROYO.91Jan24120512@govtdev-11w9.shearson.com> sarroyo@govtdev-11w9.shearson.com (Suzanne Arroyo) writes: > [Regarding passing an int(*)() to a function expecting a void(*)()] > >this works, but is messy: > > foo ( 7, 3.131592653938789, (void(*)(int, double) )bar); > > Is this actually guaranteed to work right? What if the implementation uses > a different calling sequence for a function returning void from one > returning int? For instance, the space for a return value might be > allocated by the caller. Is this allowed (I know they are allowed to use > different calling sequences for varargs functions, but is the return type > also allowed to influence the calling sequence)? If so, then foo won't > call bar properly. No, it's not guaranteed to work right. It will work on many architectures for many return types, but not all. Structure return types are the most likely candidates for misbehavior because the space for a returned structure is frequently allocated by the caller and the address passed as an additional argument, so the call does not work. It is not possible to call a mis- declared function with predictable results -- casting to the correct type may shut up the compiler, but it won't make it right. ---- Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH 45150-2789 513-576-2070 Domain: scjones@thor.UUCP Path: uunet!sdrc!thor!scjones There's a connection here, I just know it. -- Calvin
gwyn@smoke.brl.mil (Doug Gwyn) (01/26/91)
In article <2887@casbah.acns.nwu.edu> hpa@casbah.acns.nwu.edu (Peter Anvin) writes: >Turbo C++ always terminates with a hard "Type mismatch" error. Is this >correct behaviour, and if so, is there a way to declare a pointer to a >function returning *anything or void* but still specify its parameters? Of course the types did not match; that was obvious and the diagnostic was quite appropriate. There is no such thing as a C function returning polymorphic types. If the return value is sometimes needed and is an int then, and is sometimes not needed, the function should be defined as returning int. >P.S. I haven't been able to figure out... is X3J11 ANSI C *finalized* (ANSI >C-90) or are we still muddling around with working drafts? Welcome back from Outer Mongolia! There are now both American and International standards for C; the two are technically identical for the moment. ANS X3.159-1989 was approved in December 1989.
gwyn@smoke.brl.mil (Doug Gwyn) (01/26/91)
In article <1991Jan24.181041.4894@Think.COM> barmar@think.com (Barry Margolin) writes: >In article <SARROYO.91Jan24120512@govtdev-11w9.shearson.com> sarroyo@govtdev-11w9.shearson.com (Suzanne Arroyo) writes: >> foo ( 7, 3.131592653938789, (void(*)(int, double) )bar); >Is this actually guaranteed to work right? No, for as Lincoln said, calling a tail a leg doesn't make it a leg.
preston@LL.MIT.EDU (Steven Preston) (01/26/91)
In message <2887@casbah.acns.nwu.edu> hpa@casbah.acns.nwu.edu (Peter Anvin) writes: + Could someone please tell me if this is illegal in ANSI C: + void foo(int p1, double p2, void (*zoom)(int x, double y)) [definition of foo] + int bar(int baz, double quux) [definition of bar] ... + foo(7,3.141592653938789,bar); /* Turbo C++ gives hard error here */ Others have mentioned that this is indeed illegal, and that casting the address of bar() to the appropriate type will probably work but is not guaranteed. I would like to present a correct (I hope) alternative. If you must call a function through a pointer without knowing what is being returned, AND if you are not going to USE any value returned by that function, then you can just wrap the function inside of a function returning void. void bar_foo_callable(int x, double y) { (void) bar(x,y); } If you DO need to use the result, then use functions that return pointers to void. A pointer to any object can safely be cast to a pointer to void and subsequently cast back to a pointer to the original type. Of course, the original type must be known at some higher level. -- Steve Preston