mtr@ukc.ac.uk (M.T.Russell) (02/26/89)
Consider the following code fragment: typedef struct object { int id; void (*destroy)(struct object *); /* line 3 */ } object; void destroy(object *obj) { /* destroy the object */ } void f(object *obj) { (*obj->destroy)(obj); /* line 13 */ } When I compile this with gcc 1.32 (the only ANSI C compiler I have access to) I get the following: obj.c:3: warning: parameter `obj' points to incomplete type obj.c: In function f: obj.c:13: incompatible types in argument passing Is gcc right to object to incomplete types in function prototypes? If so, is there any way to specify the type of a member of a structure which is a pointer to a function taking a pointer to the structure as an argument (sorry, I can't think of a better way to phrase this :-)). One workaround is to declare destroy as void (*destroy)(void *); but this loses type information. Mark Russell mtr@ukc.ac.uk
gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/28/89)
In article <237@harrier.ukc.ac.uk> mtr@ukc.ac.uk (M.T.Russell) writes: >Is gcc right to object to incomplete types in function prototypes? Logically it might be thought to make a difference. However, we once deduced from various constraints scattered throughtout the C language that "all structure pointers have to smell the same", i.e. have the same representation. (Strictly speaking, this assumes the compiler is not applying global code analysis to identify places where shortcuts can be applied, so there should be an "as if" in there somewhere.) Therefore, the compiler should easily be able to cope with not knowing the precise structure type in your example. An incomplete array is similarly no problem. An incomplete struct or union parameter (as opposed to a pointer to one) could be more bothersome, but not noticeably worse than for incomplete data types. I don't think the pANS disallows an incomplete type in this context. Certainly the problem is not that the struct tag "object" had prototype scope, because the scope of the tag had already begun. >One workaround is to declare destroy as > void (*destroy)(void *); Better in this particular example might be void (*destroy)(); so that SOME type checking could still be performed. I don't recall any public review comments on this, but it's a good point. I hope I've interpreted this correctly..