shaked gana
shaked gana

Reputation: 13

Warning: assignment from incompatible pointer type in linked list struct

I get a lot of "assignment from incompatible pointer type" warnings, and I don't know why. The warnings appear in this part:

void addNode(linkedList* list, int board)
{
Node* newNode = createNode(board);
(list->last)->next = newNode; // this line has warning
newNode->prev = list->last; // this line has warning
}

The structs and the rest of the code is:

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

typedef struct{
    int length;
    Node* first;
    Node* last;
}linkedList;

Node* createNode(int board)
{
    Node* node = (Node*)malloc(sizeof(Node));
    node->next = NULL;
    node->prev = NULL;
    node->board = board;
    return node;
}
linkedList* createList()
{
    linkedList* list = (linkedList*)malloc(sizeof(linkedList));
    list->first = NULL;
    list->last = NULL;
    list->length = 0;
    return list;
 }

Upvotes: 0

Views: 1835

Answers (2)

rici
rici

Reputation: 241721

You never actually define struct Node.

The type which you alias (typedef) as Node is an untagged struct. When you later declare a pointer struct Node*, the compiler allows it as a pointer to an incomplete type (which is implicitly declared), but that's not the same as any type declared in your program.

A good way to declare a struct with self-referring pointers is:

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

In that formulation, the first line defines Node as an alias for the still incomplete type struct Node, which is then defined by the second declaration. struct Node is still incomplete when the Node* member declarations are encountered, but pointers to incomplete types are allowed.

One reason I'm fond of that style is that it works well with the common case in which the struct is an opaque datatype whose members are not intended for public use. In that case, the typedef can be placed in the header file, allowing pointers to the opaque type to be used in function prototypes or as local variables. The struct definition itself then goes into the implementation.

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 180201

This ...

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

... declares a tagless structure type, and defines Node as an alias for that type. It does not define the type struct Node to which its members next and prev point. That doesn't prevent pointers to such a type being declared, but that type is not the same as Node, and not compatible with it.

The easiest solution, supposing that there isn't any definition of struct Node elsewhere, is to just add that tag:

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

That gives you what you surely meant.

Note, too, that you don't inherently need a typedef at all. Having added the tag, you can refer to that type everywhere as struct Node. The typedef'd alias is a convenience only, and one that I think is way overused. All too often, typedefs obfuscate more than they help.

Upvotes: 4

Related Questions