tada@athena.mit.edu (Michael Zehr) (09/21/88)
I'm writing a graphics interface library which ends up passing a lot of pointers to functions. I've run into a problem with typedefs and prototypes: /* typedef and prototype declaration of a widget */ typedef void (*Keyboard_widget)(int key, void *data); Keyboard_widget kb_widget1; /* definition of a widget */ void kb_widget1(int c, void *data) {...} I get a "conflicts with previous declaration" at that point. If I try to define the widget by the typedef, what syntax do i use??? Keyboard_widget kb_widget1 /* where do the formal parameters go??? */ {...} Anyone have any suggestions? (The reason why i want to use the typedef is that i have to pass objects of type Keyboard_widget into some functions, and store them in structures. i can use a "normal" prototype for the function but is it strictly conforming when i later on pass a pointer to that function to a procedure that's expecting a Keyboard_widget???) -michael j zehr
gwyn@smoke.ARPA (Doug Gwyn ) (09/21/88)
In article <7135@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >typedef void (*Keyboard_widget)(int key, void *data); >void kb_widget1(int c, void *data) >I get a "conflicts with previous declaration" at that point. If I try >to define the widget by the typedef, what syntax do i use??? Use exactly the syntax of the typedef, minus "typedef", with the type name replaced by the identifier. I.e. void (*kb_widget1)(int key, void *data) { ... } >Keyboard_widget kb_widget1 /* where do the formal parameters go??? */ >{...} This one is a mystery to me too. The compilers I've tried this on are unhappy no matter how I try to use the typedef in defining the function. Fortunately the explicit definition is completely compatible, but it would be nice if the typedef method worked.
karl@haddock.ima.isc.com (Karl Heuer) (09/21/88)
In article <8543@smoke.ARPA> gwyn@smoke.ARPA (Doug Gwyn) writes: > void (*kb_widget1)(int key, void *data) { ... } That can't be right. If kb_widget1 is supposed to be a pointer to a function, then its definition would take an initializer, not a function body. >In <7135@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >>typedef void (*Keyboard_widget)(int key, void *data); It looks like what you meant to say was: typedef void Keyboard_widget(int key, void *data); which should clear up the error message. No, you can't use the typedef when you actually declare the function, since (as you noted) there's no place to put the formal parameters. (There's a note in the dpANS that explicitly forbids inheriting the parameter list through a typedef.) Note that the typedef is now "function". To declare an object of type pointer to function, you should use "Keyboard_widget *pf;". Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
gwyn@smoke.ARPA (Doug Gwyn ) (09/21/88)
In article <7785@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >In article <8543@smoke.ARPA> gwyn@smoke.ARPA (Doug Gwyn) writes: >> void (*kb_widget1)(int key, void *data) { ... } >That can't be right. If kb_widget1 is supposed to be a pointer to a function, >then its definition would take an initializer, not a function body. Hm, that's probably right. "Never mind." >>In <7135@bloom-beacon.MIT.EDU> tada@athena.mit.edu (Michael Zehr) writes: >>>typedef void (*Keyboard_widget)(int key, void *data); >It looks like what you meant to say was: > typedef void Keyboard_widget(int key, void *data); That's more what I had in mind anyway. I still can't get some of the PCC-based compilers around here to let me use function typedefs in the actual function definition. (Of course the parameter list is not an issue since old-style C doesn't have prototypes.)
chris@mimsy.UUCP (Chris Torek) (09/21/88)
>In article <7135@bloom-beacon.MIT.EDU> tada@athena.mit.edu >(Michael Zehr) asks: >>typedef void (*Keyboard_widget)(int key, void *data); >>void kb_widget1(int c, void *data) >>I get a "conflicts with previous declaration" at that point. If I try >>to define the widget by the typedef, what syntax do i use??? In article <8543@smoke.ARPA> gwyn@smoke.ARPA (Doug Gwyn) answers: >Use exactly the syntax of the typedef, minus "typedef", with the >type name replaced by the identifier. Right, but: >I.e. > void (*kb_widget1)(int key, void *data) { ... } > >>Keyboard_widget kb_widget1 /* where do the formal parameters go??? */ >>{...} > >This one is a mystery to me too. The formal parameters go nowhere: you have declared a type (with the typedef) or an object (without the typedef) which translates to `pointer to function(int, void *) returning void'. Since it is a pointer, it cannot be a function. The syntax for `function returning pointer to function(int, void *) returning void' is, of course, void (*here_is_fn(type1 arg1, etc))(int, void *) { ... } and the formal parameters go where` type1 arg1, etc' sits. Using a typedef for `pointer to function(int, void *) returning void', it simplifies to: /* pointer to function arg int arg pointer to void return void */ /* ^ ^ ^ ^ ^ ^ ^ ^ ^ */ typedef (*pfAiApvRv)(int, void *); pfAiApvRv here_is_fn(type1, arg1, etc) { ... } Note that you cannot use a typedef to define a function type: i.e., `typedef func_arg_int_ret_int int(int);' is illegal. The problem is that, given this definition, there is nowhere to put the parentheses and the formal, so that transforming /* identity fn */ int identity(int i) { return i; } to func_arg_int_ret_int identity { return i??? } leaves us nowhere to declare `i'. (If we needed no arguments, it might work, but it makes the grammar inordinately difficult.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ggs@ulysses.homer.nj.att.com (Griff Smith) (09/22/88)
In article <7135@bloom-beacon.MIT.EDU>, tada@athena.mit.edu (Michael Zehr) writes: > > I'm writing a graphics interface library which ends up passing a lot > of pointers to functions. I've run into a problem with > typedefs and prototypes: > /* typedef and prototype declaration of a widget */ > > typedef void (*Keyboard_widget)(int key, void *data); > > Keyboard_widget kb_widget1; > > /* definition of a widget */ > > void kb_widget1(int c, void *data) > {...} > I get a "conflicts with previous declaration" at that point. If I try > to define the widget by the typedef, what syntax do i use??? /* Define the layout of a keyboard_widget function */ typedef void kb_widg_fn(int key, void *data); /* Define a type that is a pointer to a keyboard_widget function */ typedef kb_widg_fn* Keyboard_widget; /* I'm going to use kb_widget1, which is a keyboard_widget function */ kb_widg_fn kb_widget1; /* And here it is */ void kb_widget1(int c, void *data) {} /* This is accepted by C++, release 2.0; I can't speak for ANSI C */ -- Griff Smith AT&T (Bell Laboratories), Murray Hill Phone: 1-201-582-7736 UUCP: {allegra|ihnp4}!ulysses!ggs Internet: ggs@ulysses.att.com
gwyn@smoke.ARPA (Doug Gwyn ) (09/22/88)
In article <13664@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >Note that you cannot use a typedef to define a function type... That's a real pity too. We have an application where a programmer has to supply functions that match a predetermined interface (they are called via pointers in a struct). It would be wonderful if a typedef could be used for defining the function as well as declaring the pointers in the struct. Yet another thing to fix in the "D" language.
english@panarea.usc.edu (Joe English) (09/23/88)
In article <13664@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >Note that you cannot use a typedef to define a function type: i.e., >`typedef func_arg_int_ret_int int(int);' is illegal. The problem is >that, given this definition, there is nowhere to put the parentheses >and the formal, so that transforming > > /* identity fn */ > int identity(int i) { return i; } > >to > > func_arg_int_ret_int identity { return i??? } > >leaves us nowhere to declare `i'. (If we needed no arguments, it >might work, but it makes the grammar inordinately difficult.) I found out by accident that such a construct does work in Borland's Turbo C (tm): I had a slew of functions that took the same parameters to go into an array, and I included a prototype in the typedef to enable type-checking when they were called indirectly. It turns out that if the typedef includes parameter names, like typedef int func_t(int i, int j); then function definitions will only work like this: func_t foo { return i+j; } !!! Of course, func_t foo(int a, int b) is a "function returning a function," so the omission of the parameters in the definition makes 'sense.' I just tried this construct on gcc, and it (quite rightly) doesn't work at all. Question: is giving parameter names in a function declaration (void foo(int i,int j);) part of the standard? The Turbo manual says to do this for clarity, but I will drop this practice if it is nonportable. /|/| Joe English -----< | | j.e. O \|\| ARPA: english%lipari@oberon.usc.edu
chris@mimsy.UUCP (Chris Torek) (09/23/88)
In article <12326@oberon.USC.EDU> english@panarea.usc.edu (Joe English) writes: >I found out by accident that such a construct does work in Borland's >Turbo C (tm): ... >typedef int func_t(int i, int j); > >func_t foo { > return i+j; >} > >!!! Of course, func_t foo(int a, int b) is a "function returning a >function," so the omission of the parameters in the definition makes >'sense.' True. The dpANS says that the definition above (but, I think, NOT the typedef declaration; for this I would have to check) is illegal. >I just tried this construct on gcc, and it (quite rightly) >doesn't work at all. Incidentally, this has always bothered me about standard Pascal: type msgtype = array [1..80] of char; { or whatnot } procedure foo(i, j: integer; var msg: msgtype); forward; ... many pages of code ... procedure foo; begin { do stuff with i, j, and msg } end; ... One has to wonder where `i', `j', and `msg' came from: Information that is by rights purely local appears in a nonlocal place. >Question: is giving parameter names in a >function declaration (void foo(int i,int j);) part of the standard? Yes. The names themselves, however, are to be ignored by the compiler (Turbo C is obviously not doing this). (Whether this means that void foo(int i, char *i); is legal I do not know.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
karl@haddock.ima.isc.com (Karl Heuer) (09/24/88)
In article <13664@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >Note that you cannot use a typedef to define a function type: i.e., >`typedef func_arg_int_ret_int int(int);' is illegal. On the contrary, it *is* legal, and is even used as an example in the dpANS. However, such a defined type can only be used to declare a function, not to define one. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
jim.nutt@p11.f15.n114.z1.fidonet.org (jim nutt) (09/24/88)
> From: english@panarea.usc.edu (Joe English) > Newsgroups: comp.lang.c > > doesn't work at all. Question: is giving parameter names in a > function declaration (void foo(int i,int j);) part of the standard? > The Turbo manual says to do this for clarity, but I will drop this > practice if it is nonportable. yes. jim nutt 'the computer handyman' -- St. Joseph's Hospital/Medical Center - Usenet <=> FidoNet Gateway Uucp: ...{gatech,ames,rutgers}!ncar!noao!asuvax!stjhmc!15.11!jim.nutt
lmiller@venera.isi.edu (Larry Miller) (09/28/88)
In article <13709@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <12326@oberon.USC.EDU> english@panarea.usc.edu (Joe English) writes: > >(Whether this means that > > void foo(int i, char *i); > >is legal I do not know.) >-- >In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) >Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris Identifiers in prototypes have scope to the end of the declaration. The above is not legal (though notice the ancient date on my copy of the draft. [Ref: Draft standard, Nov., 1985 (!), Ss C.5.3.3] In a declaration that is not a function definition [i.e., a function prototype], any identifier declared in the list has function prototype scope, which extends to the end of the declaration... Larry Miller lmiller@venera.isi.edu (no uucp) USC/ISI 213-822-1511 4676 Admiralty Way Marina del Rey, CA. 90292