forward declared structures

Morris Keesan keesan at bbncca.ARPA
Fri Aug 3 01:31:10 AEST 1984


>I have a question on forward declarations of structures in C.  Kernighan and
>Ritchie does not answer the question and to me the behavior of the Berkeley
>Unix C compiler is without question wrong.  To wit:
>
>struct s *ps;
>
>main() {
>    struct s { 
>	 int i1, i2;
>	 };
>}
>foo() {
>    ps->i1 = 33;
>}
>
>My question is whether field i1 should be known in foo.  In the Berkeley
>Compiler, it is known if and only if there is a different struct with a
>field i1 declared before main is declared !?  If there is such a field,
>the type and offset of i1 are correct, otherwise you get an undefined field
>reference error.
>
>I discovered this while implementing a C compiler for a class and wanted to 
>follow real C instead of the simplification of structures that our professor
>recommended.  My solution was to say that the declaration of the structure was
>exported to the block level of the first use of the forward declaration and
>no further.   Any better ideas?
>
>Bill Smith
>princeton!siemens!wws

    Indeed, the Berkeley compiler is behaving incorrectly here, but it's
easy to see how the bug crept in.  The problem is not with knowing about
field i1.  That is getting treated correctly.  In the example, element i1 is
not known in the scope of foo, and if another structure is declared with
structure member i1, then i1 is known inside foo.  See section 14.1 of the
C Reference Manual, which says, "the expression before a -> is required only
to be a pointer or an integer.  If a pointer, it is assumed to point to a
structure of which the name on the right is a member."  So if i1 is defined
in a scope which foo inherits, then it doesn't matter what the type of ps is.
    The error here is in allowing the declaration of ps as a pointer to an
undeclared structure.  Playing with my compiler, descended from the Ritchie
PDP-11 C compiler, I discover that I can declare a pointer to a structure
whether or not that structure is ever declared, either in the scope of the
pointer declaration, in an inner scope, forward, or backward.  This is
clearly illegal:  C Ref. Man. section 8.5:

	A structure or union specifier of the second form, that is, one of
	    struct identifier { struct-decl-list }
	    union identifier { struct-decl-list }
	declares the identifier to be the structure tag (or union tag) of
        the structure specified by the list.  A SUBSEQUENT declaration may
	then use the third form of specifier, one of
	    struct identifier
	    union identifier
	Structure tags allow definition of self-referential structures; . . .
	a structure or union may contain a pointer to an instance of itself.

Capitalization of SUBSEQUENT is mine.  Implicitly within this "subsequent"
means subsequent to the "struct identifier {" rather than subsequent to the
entire declaration, otherwise structures containing pointers to themselves
would not be allowed.  It looks like it was too much work to keep track of
whether the compiler was in the middle of declaring "struct s", and so in
order to allow structures to point to themselves, the compiler writer(s)
decided to allow any declaration of "pointer to structure", regardless of
whether the structure was yet declared.
-- 
			    Morris M. Keesan
			    {decvax,linus,ihnp4,wivax,wjh12,ima}!bbncca!keesan
			    keesan @ BBN-UNIX.ARPA



More information about the Comp.lang.c mailing list