Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

forward declaration of structs (again)

18 views
Skip to first unread message

M Clarke

unread,
Jul 2, 1999, 3:00:00 AM7/2/99
to
Hi,

I have a problem with forward declaration of structs in ANSI C.
I know this thread has cropped up before but I only caught the tail
end of it, and this may be slightly different...

I like to define my structs at the bottom of a file,
and refer to them at the top, ie. before definition.

eg.
===file.c===

/* forward declaration of my_struct needed here */


/* use of my_struct before definition */
void *pv = (void *) my_struct;


/* lots of code here */


/* definition of my_struct */
struct STRUCT_TYPE my_struct[]=
{
{ 1,2,"a"},
{ 1,3,"b"},
};
==end of file.c=======

so i need some way of forward declaring my structs.
I was using
struct STRUCT_TYPE mystruct[];

but if I mispell the forward declaration AND the reference to it
I will end up with, in this example, pv pointing to the wrong place.
ie. the declaration will be accepted as a definition of an empty array
(this is my interpretation of whats happening).

Because I have a large number of these structs it is important for me
to have the compiler spot this error.
I dont have my K&R with me, can anyone help me with this?

thanks

M Clarke


Kaz Kylheku

unread,
Jul 3, 1999, 3:00:00 AM7/3/99
to
On Fri, 02 Jul 1999 23:11:42 GMT, M Clarke <mcl...@nospam.pizza.demon.co.uk>
wrote:

>Hi,
>
>I have a problem with forward declaration of structs in ANSI C.
>I know this thread has cropped up before but I only caught the tail
>end of it, and this may be slightly different...

Yes, this is different because you are talking about declaring objects. That is
to say, instances of a struct type. Not the struct type itself.

>I like to define my structs at the bottom of a file,
>and refer to them at the top, ie. before definition.
>
>eg.
>===file.c===
>
>/* forward declaration of my_struct needed here */

The C language doesn't exactly have forward declarations. Forward
declarations are a workaround hack in the Pascal language to
support mutually recursive functions.

In C, identifiers may be declared more than once in the same scope
provided that certain restrictions are met, but this isn't called
forward declaration.


>
>/* use of my_struct before definition */
>void *pv = (void *) my_struct;
>
>
>/* lots of code here */
>
>
>/* definition of my_struct */
>struct STRUCT_TYPE my_struct[]=
>{
> { 1,2,"a"},
> { 1,3,"b"},
>};
>==end of file.c=======
>
>so i need some way of forward declaring my structs.
>I was using
> struct STRUCT_TYPE mystruct[];
>
>but if I mispell the forward declaration AND the reference to it
>I will end up with, in this example, pv pointing to the wrong place.

That's because the above is not only a declaration but it also is a special
kind of definition called a tentative definition. A tentative definition
becomes an actual definition sometime before the end of the translation unit.
A tentative definition may be augmented by a later actual definition---that is,
a declaration with an initializer. If such a thing does not appear, then the
behavior is as if a redefinition appeared at the end of the translation unit
with the initializer { 0 }.

What you want is a way of writing the declaration in such a way that it
is not a tentantive definition but rather a pure declaration. This is
accomplished by explicitly stating the extern storage class, and omitting
the initializer:

extern struct STRUCT_TYPE mystruct[];

If this object is referred to, and a definition does not appear somewhere in
the program, the behavior is undefined. Most programming systems, however,
diagnose this with a fairly clear link error. Thus in the event of a
misspelling of the definition, you get the diagnostic you are looking for.

The best way to avoid error, however, is to avoid useless duplicity whenever
you can. There is no reason for you to write the definition with initializer
at the end, so don't do it. Write exactly one declaration with an initializer.
object by supplying the initial value.

Here is another reason: you probably want to make this array object static so
that it is private to the translation unit. There is no way to write a pure
declaration for a file scope static object without first writing at least
a tentative definition. A file scope static object declaration with no
initializer is a tentative definition if no prior declaration exists.

>ie. the declaration will be accepted as a definition of an empty array (this
>is my interpretation of whats happening).

The declaration will be accepted as a tentative definition of an array of
incomplete type. If no other declaration appears by the end of the translation
unit, the compiler is required to pretend that at the end there is a
declaration that looks like:

struct STRUCT_TYPE mystruct[] = { 0 };

So you end up with a one element array. This is such an obscure language
feature that I would not count on too many compilers getting it right.

0 new messages