49

I am writing a LinkedList in C, the below code represent my Node definition.

typedef struct {
    int value;
    struct Node* next;
    struct Node* prev;
} Node;

I understand (or think that I do) that struct Node not the same as typedef struct Node. Granted my code compiles and runs as it's supposed to, however, I get a lot of warnings when assigning next and prev (warning: assignment from incompatible pointer type). I am guessing that this has to do with how I'm defining them in the Node structure. I uploaded the full source here

So, if that is indeed the problem, how should I define next and prev inside the typedef struct Node?

I was worried this may be a repost, but couldn't quite find what I was looking for. Thanks.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Kenny Cason
  • 12,109
  • 11
  • 47
  • 72
  • 4
    having pointers to head and tail make append and prepend O(1) instead of O(n). Let me know if you see other errors as this is mainly just an exercise to keep my C skills somewhat fresh after all these years of Java.. – Kenny Cason Oct 21 '10 at 13:52
  • The warnings come when you try to do `my_node->next = my_other_node` – Josiah Yoder Sep 12 '18 at 19:42

2 Answers2

87

You need to do it in this order:

typedef struct Node Node;

struct Node
{
  int value;
  Node *next;
  Node *prev;
};

That doesn't do exactly what you asked, but it solves the problem and is how this generally is done. I don't think there's a better way.

This kind of forward declaration has a second usage, in data hiding. If the list was implemented in a library, you could have just the typedef in the public header, along with functions like:

Node * list_new(void);
Node * list_append(Node *head, Node *new_tail);
size_t list_length(const Node *head);

This way, users of the library don't have easy access to the internals of your library, i.e. the fields of the Node structure.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • 2
    Yes. A forward declaration ( http://en.wikipedia.org/wiki/Forward_declaration ) is exactly what is needed. – Eric Towers Oct 21 '10 at 13:44
  • Oh wow. I think I tried every combination except that one! thanks! warnings all gone! :) – Kenny Cason Oct 21 '10 at 13:45
  • Right, I'm aware of forward declarations and used them throughout C++, but just never had this particular circumstance come up before, let alone with typedef/structs :) – Kenny Cason Oct 21 '10 at 13:47
  • 8
    Actually it would have worked to just add `Node` after the first `struct` in OP's code. – R.. GitHub STOP HELPING ICE Oct 21 '10 at 15:24
  • 1
    @R.. Thanks That worked for me as well. Is there a preference between the two methods mentioned? – Kenny Cason Oct 21 '10 at 15:44
  • 1
    Either is just as good. Personally I usually only use a separate forward declaration and typedef (as in unwind's answer) is when I want to put the declaration in a header and the definition in an implementation file. – R.. GitHub STOP HELPING ICE Oct 21 '10 at 16:01
  • @r-github-stop-helping-ice @kenny-cason The combined approach only works for C++ as written. For C, you'd have to change `Node *next;` to `struct Node *Next;`. If you use the forward declaration method with the separate statement, then you can leave out the `struct` keyword. – Harvey Mar 23 '22 at 18:59
37

Another acceptable way and with the least change to OP's code is the following:

typedef struct NodeT {
    int value;
    struct NodeT * next;
    struct NodeT * prev;
} Node;

Note the introduction of NodeT and its usage in next and prev until Node is available.

Arun
  • 19,750
  • 10
  • 51
  • 60