Re: incorrect warning?



Duncan Muirhead <noone@xxxxxxxxxxxx> writes:
[...]
Thank you, all, for your replies. However I am still somewhat bemused.
If I alter the program by adding
typedef struct
{ struct thingTag* p;
} entity;
before the typedef for show, no warnings are generated. If I add it after
show, show (but not entity) generates warnings. Is this difference in
references to undeclared types in functions and structs an oddity of the
language or the compiler?

Please trim quoted material when you post a followup. Provide enough
context so we can understand what's going on; that seldom requires
quoting everything.

Here's the original (incorrect) program:
========================================
#include <stdio.h>

typedef void (*show)( struct thingTag *);

typedef struct thingTag
{ show f;
double v;
} thing;

void show_metres( thing* p)
{ printf( "%f m\n", p->v);
}

int main( int argc, char** argv)
{
thing T;
T.v = 1.7;
T.f = show_metres;
T.f( &T);
return 1;
}
========================================

The first occurrence of "struct thingTag" is inside the typedef for
"show". Since there's been no complete declaration of that type, the
compiler treats it as an implicit declaration of a new incomplete
type; normally, such an incomplete type would be completed later. But
in this case, the new incomplete type appears within a function
prototype, and its scope is limited to that prototype. It's just as
if you had declared, within a function:

{
struct incomplete_type;
}
struct incomplete_type {
int x;
int y;
}

The scope of the incomplete declaration is limited to the
brace-enclosed block in which it appears. By the time we see the
complete declaration, the previous incomplete declaration no longer
exists.

When you add your

typedef struct
{ struct thingTag* p;
} entity;

*before* the "show" typedef, you mention "struct thingTag". This is
now treated as a new incomplete type, but since it's not inside the
prototype, its scope extends to the end of the file. (This is
incidental to the declaration of "entity".) Now the compiler sees the
occurrence of "struct thingTag" within the prototype in the "show"
typedef as a reference to the existing incomplete type, rather than as
an implicit declaration of a new one.

If you put the typedef for "entity" *after* the "show" typedef, then
the "struct thingTag" within the prototype declares a new incomplete
type with a limited scope, and the compile warns you about it (because
that's not a useful thing to do). The "struct thingTag" within the
typedef for "entity" *also* declares a new incomplete type (since the
"struct thingTag" from the prototype is out of scope and therefore
doesn't exist), but it's not of such limited scope, so the compiler
doesn't warn you about it.

(This whole business of something being a new declaration if and only
if the thing hasn't already been declared is, IMHO, unfortunate and
confusing, and can mask some serious errors, but there it is.)

If you need a forward declaration of a structure, just do it directly,
not as part of another declaration.

And again, you should seriously consider getting rid of any typedefs
for struct types. By having just one name for the type, you have
fewer things to keep track of.

--
Keith Thompson (The_Other_Keith) kst-u@xxxxxxx <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
.



Relevant Pages

  • Re: incorrect warning?
    ... The first occurrence of "struct thingTag" is inside the typedef for ... Since there's been no complete declaration of that type, ... such an incomplete type would be completed later. ... struct incomplete_type; ...
    (comp.lang.c)
  • Re: how to define a function pointer variable witout typdef?
    ... I have N869 and it makes no reference to typedef reserving ... A /definition/ of an identifier is a declaration for that ...
    (comp.lang.c)
  • Re: typedef function pointer
    ... the semantics for typedef is: ... That's the syntax, not the semantics. ... to be an array of 20 ints, the declaration is ... to a function taking to int arguments and returning it, ...
    (comp.lang.c)
  • Re: how to define a function pointer variable witout typdef?
    ... > typedef name, the entity is an alias ... > typedef int foo; ... I think that a complete structure declaration: ... struct list_node *next; ...
    (comp.lang.c)
  • Re: Porting from visual C to gcc problem
    ... >The declaration above defines the identifier 'DNIS_TIMER_CALLBACK' as ... the compiler must have come across the typedef ... >C is a scoped language, and one of the scopes is "prototype scope". ... >int func; ...
    (comp.lang.c.moderated)