157

I haven't been writing C for very long, and so I'm not sure about how I should go about doing these sorts of recursive things... I would like each cell to contain another cell, but I get an error along the lines of "field 'child' has incomplete type". What's up?

typedef struct Cell {
  int isParent;
  Cell child;
} Cell;
Community
  • 1
  • 1
Ziggy
  • 21,845
  • 28
  • 75
  • 104

9 Answers9

223

Clearly a Cell cannot contain another Cell as it becomes a never-ending recursion.

However a Cell CAN contain a pointer to another Cell.

typedef struct Cell {
  bool isParent;
  struct Cell* child;
} Cell;
Neuron
  • 5,141
  • 5
  • 38
  • 59
Andrew Grant
  • 58,260
  • 22
  • 130
  • 143
  • 9
    @cs01 No, `Cell` is not in scope yet. – fredoverflow Dec 30 '15 at 13:28
  • 1
    It *would* make sense. Python allows it and even allows serialization of such an object. Why not C++? – noɥʇʎԀʎzɐɹƆ Jun 06 '16 at 01:06
  • 2
    I get warnings when I try to assign `Cell*` to `cell->child`. – Tomáš Zato Nov 26 '16 at 23:02
  • 8
    @noɥʇʎԀʎzɐɹƆ Because Python abstracts away pointers so that you don't notice them. Since `struct`s in C basically just store all of their values next to each other, it would be impossible to actually store a struct in itself (because that struct would have to contain another one and so on, leading to a memory structure of infinite size). – jazzpi Feb 03 '17 at 15:31
  • 2
    For an explanation of the use of `struct Cell`, see [this answer](https://stackoverflow.com/a/588729/5223757). – wizzwizz4 May 27 '17 at 13:53
  • 1
    Re "*Python allows it and even allows serialization of such an object.*", The fact that a structure can't include itself is universal as it would create an infinitely large structure. Python may not use the `*` syntax for pointers/references, but it still uses a pointer/reference as required here. – ikegami Jun 29 '19 at 06:55
  • 1
    Note C11 [§6.7.2.1 Structure and union specifiers ¶3](https://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p3): _A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), …_ – Jonathan Leffler Nov 14 '19 at 06:33
35

In C, you cannot reference the typedef that you're creating withing the structure itself. You have to use the structure name, as in the following test program:

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

typedef struct Cell {
  int cellSeq;
  struct Cell* next; /* 'tCell *next' will not work here */
} tCell;

int main(void) {
    int i;
    tCell *curr;
    tCell *first;
    tCell *last;

    /* Construct linked list, 100 down to 80. */

    first = malloc (sizeof (tCell));
    last = first;
    first->cellSeq = 100;
    first->next = NULL;
    for (i = 0; i < 20; i++) {
        curr = malloc (sizeof (tCell));
        curr->cellSeq = last->cellSeq - 1;
        curr->next = NULL;
        last->next = curr;
        last = curr;
    }

    /* Walk the list, printing sequence numbers. */

    curr = first;
    while (curr != NULL) {
        printf ("Sequence = %d\n", curr->cellSeq);
        curr = curr->next;
    }

    return 0;
}

Although it's probably a lot more complicated than this in the standard, you can think of it as the compiler knowing about struct Cell on the first line of the typedef but not knowing about tCell until the last line :-) That's how I remember that rule.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
14

From the theoretical point of view, Languages can only support self-referential structures not self-inclusive structures.

Sundar
  • 414
  • 4
  • 12
13

There is sort of a way around this:

struct Cell {
  bool isParent;
  struct Cell* child;
};

struct Cell;
typedef struct Cell Cell;

If you declare it like this, it properly tells the compiler that struct Cell and plain-ol'-cell are the same. So you can use Cell just like normal. Still have to use struct Cell inside of the initial declaration itself though.

  • 11
    why did you write `struct Cell;` again ? – MAKZ Mar 08 '15 at 03:43
  • @MAKZ because the typedef hasn't been executed by the compiler at the time that it's compiling the definition of `struct Cell`. – Tyler Crompton Oct 02 '15 at 22:36
  • 2
    @TylerCrompton if the above code block is put into a single C source file, then the typedef _has_ been "executed by the compiler", making the extra `struct Cell;` redundant. If, however, for some reason you put the last two lines into a header file which you include _before_ you define the `Cell` struct with the first four lines, *then* the extra `struct Cell;` is nececairy. – yyny Mar 07 '16 at 19:06
  • This doesn't even compile under C99 standard. – Tomáš Zato Nov 26 '16 at 23:03
  • 2
    @YoYoYonnY No, you can still just write `typedef struct Cell Cell;` and it will make `Cell` an alias for `struct Cell`. It doesn't matter whether the compiler has seen `struct Cell { .... }` before. – melpomene Feb 28 '18 at 01:40
  • @TomášZato — yes, it does compile under C90, C99, C11, C18. – Jonathan Leffler Nov 14 '19 at 06:24
7

Pre-typedef the structure with,structure tag as:

//declare new type 'Node', as same as struct tag
typedef struct Node Node;
//struct with structure tag 'Node'
struct Node
{
    int data;
    //pointer to structure with custom type as same as struct tag
    Node *nextNode;
};
//another pointer of custom type 'Node', same as struct tag
Node *node;
Keynes
  • 109
  • 1
  • 4
7

I know this post is old, however, to get the effect you are looking for, you may want to try the following:

#define TAKE_ADVANTAGE

/* Forward declaration of "struct Cell" as type Cell. */
typedef struct Cell Cell;

#ifdef TAKE_ADVANTAGE
/*
   Define Cell structure taking advantage of forward declaration.
*/
struct Cell
{
   int isParent;
   Cell *child;
};

#else

/*
   Or...you could define it as other posters have mentioned without taking
   advantage of the forward declaration.
*/
struct Cell
{
   int isParent;
   struct Cell *child;
};

#endif

/*
    Some code here...
*/

/* Use the Cell type. */
Cell newCell;

In either of the two cases mentioned in the code fragment above, you MUST declare your child Cell structure as a pointer. If you do not, then you will get the "field 'child' has incomplete type" error. The reason is that "struct Cell" must be defined in order for the compiler to know how much space to allocate when it is used.

If you attempt to use "struct Cell" inside the definition of "struct Cell", then the compiler cannot yet know how much space "struct Cell" is supposed to take. However, the compiler already knows how much space a pointer takes, and (with the forward declaration) it knows that "Cell" is a type of "struct Cell" (although it doesn't yet know how big a "struct Cell" is). So, the compiler can define a "Cell *" within the struct that is being defined.

Shawn
  • 71
  • 1
  • 2
3

Lets go through basic definition of typedef. typedef use to define an alias to an existing data type either it is user defined or inbuilt.

typedef <data_type> <alias>;

for example

typedef int scores;

scores team1 = 99;

Confusion here is with the self referential structure, due to a member of same data type which is not define earlier. So In standard way you can write your code as :-

//View 1
typedef struct{ bool isParent; struct Cell* child;} Cell;

//View 2
typedef struct{
  bool isParent;
  struct Cell* child;
} Cell;

//Other Available ways, define stucture and create typedef
struct Cell {
  bool isParent;
  struct Cell* child;
};

typedef struct Cell Cell;

But last option increase some extra lines and words with usually we don't want to do (we are so lazy you know ;) ) . So prefer View 2.

vineetv2821993
  • 927
  • 12
  • 25
  • Your explanation of the `typedef` syntax is incorrect (consider e.g. `typedef int (*foo)(void);`). Your View 1 and View 2 examples don't work: They make `struct Cell` an incomplete type, so you can't actually use `child` in your code. – melpomene Feb 28 '18 at 01:38
1

A Structure which contain a reference to itself. A common occurrence of this in a structure which describes a node for a link list. Each node needs a reference to the next node in the chain.

struct node
{
       int data;
       struct node *next; // <-self reference
};
Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
1

All previous answers are great , i just thought to give an insight on why a structure can't contain an instance of its own type (not a reference).

its very important to note that structures are 'value' types i.e they contain the actual value, so when you declare a structure the compiler has to decide how much memory to allocate to an instance of it, so it goes through all its members and adds up their memory to figure out the over all memory of the struct, but if the compiler found an instance of the same struct inside then this is a paradox (i.e in order to know how much memory struct A takes you have to decide how much memory struct A takes !).

But reference types are different, if a struct 'A' contains a 'reference' to an instance of its own type, although we don't know yet how much memory is allocated to it, we know how much memory is allocated to a memory address (i.e the reference).

HTH

m.eldehairy
  • 695
  • 8
  • 10