Simon Storfors
Simon Storfors

Reputation: 23

C Struct typedef and declaration causing pointer errors

I've tried and distill the following code as much as possible:

#include <stdlib.h>

typedef struct item{
    struct item *next;
}item;

void addItem(item *list)
{
    item *newItem = list;
    while(newItem->next != NULL){
        newItem = newItem->next;
    }

    newItem->next = malloc(sizeof(item));
    newItem->next->next = NULL;
}

int main()
{
    item *groceryList = NULL;
    groceryList = malloc(sizeof(item));
    if(groceryList == NULL)
        return 1;
    groceryList->next = NULL;

    addItem(groceryList);

    return 0;
}

This compiles fine. But changing the struct declaration to (or any combination of the changes):

typedef struct{ /*Removed "item"*/
    item *next; /*Removed "struct"*/
}item;

Causes the following errors when compiling:

structpointertest.c:11:11: warning: assignment from incompatible pointer type structpointertest.c:15:15: error: request for member 'next' in something not a structure or union

I don't understand what in the struct declaration is causing this issue? Does it have something to do with the fact I'm using a nested struct?

Thanks.

Upvotes: 0

Views: 639

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409136

In C you must declare things before you can use them. When you do

typedef struct item { ... }

the struct item part is a declaration telling the compiler that there exists a structure name item. That means you could use it later, even inside the structure to define a pointer to itself.

When you do

typedef struct { ... } item;

you are not giving the structure a name, and the type-alias item is declared after the structure, so it can't be used inside the structure.

The simple solution is to use the first way. Another solution is to declare the type-alias before the structure, like

typedef struct item item;
struct item
{
    item *next;  // Can use type-alias, as it has been declared up above
};

Either way, you must still give the structure itself a name.

Also note that struct item *next; (or item *next;) declares a member variable that is a pointer to the structure, it's not the actual structure itself nested recursively. Creating a pointer to something that haven't been fully defined yet is okay.

Upvotes: 4

Related Questions