anupamb
anupamb

Reputation: 482

Why does forward declaration of struct not work?

I wrote a small code in C in which two struct types were defined which have members of each other in their definition. Case 1: If the struct foo is defined before struct bar, the code is compiled as expected. Case 2: If struct foo is defined after struct bar it will not compile which is also expected as there is no way to know the memory requirement of a struct foo variable. But I was expecting it will compile if a forward declaration of struct foo is used in case 2. But it does not work. What am I missing?

#include<stdio.h>
#include<stdlib.h>

struct foo; // forward declaration

struct bar
{
  int a;
  struct bar *next;
  struct foo ch;
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};


int main()
{
  struct bar p;
  return(0);
}

Upvotes: 2

Views: 9582

Answers (3)

Arjun Mathew Dan
Arjun Mathew Dan

Reputation: 5318

If a struct type X appears only as a pointer type in a structure declaration or its functions, and the code in the header file does not attempt to access any member variables of X, then you should not #include X.h, but instead make an incomplete declaration of X (also called a "forward" declaration) before the first use of X. Here is an example in which a structure type Thing refers to X by a pointer:

struct X;  /* incomplete ("forward") declaration */

struct Thing {
  int i;
  struct X* x_ptr;
};

The compiler will be happy to accept code containing pointers to an incompletely known structure type, basically because pointers always have the same size and characteristics regardless of what they are pointing to. Typically, only the code in the .c file needs to access the members (or size) of X, so the .c file will #include "X.h". This is a powerful technique for encapsulating a module and decoupling it from other modules.

That is, it would work correctly if your code was something like :

#include<stdio.h>
#include<stdlib.h>

struct foo; // forward declaration

struct bar
{
  int a;
  struct bar *next;
  struct foo *ch;       /* MODIFIED LINE */
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};


int main()
{
  struct bar p;
  return(0);
}

But in your case, struct bar is having an "element" of type struct foo. Hence it will give error field has incomplete type.

Also for your information, see the below snippet (will work perfectly):

#include<stdio.h>
#include<stdlib.h>

struct bar
{
  int a;
  struct aabar *next;  /* MODIFIED LINE - aabar never declared */
  struct foo *ch;
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};

int main()
{
  struct bar p;
  return(0);
}

Upvotes: 2

Thanushan
Thanushan

Reputation: 532

In your struct foo the element nx is a pointer, so defining struct foo doesn't require memery size. However, on struct bar the element ch is not a pointer, so the defining struct bar needs to know the size of struct foo. The forward declaration doesn't specify the memory size, the definition does.

Upvotes: 0

vlad_tepesch
vlad_tepesch

Reputation: 6925

forward declaration only informs the compiler that there is something that is called foo it does nothing says about size. you can use foo* since this is a pointer of known size but not foo itself because the size is unknwon, so the compiler does not know how the memory layout of barshould look like.

And the compiler only do a single pass through your document. so it cannot know the strucutre that is defined ahead.

Upvotes: 6

Related Questions