0

Sorry first for my bad English. I'm begginer in C, trying to make a Singly Linked List. This is my setup of the List:

#include <stdio.h>
#include <stdlib.h>
typedef int Element;
struct
{
    Element Data;
    struct Node *Next;
} Node;

typedef struct Node *Position;
typedef Position List;

This is how I initialize this Struct (i dont know if this function is wrong):

void resetList(List *L)
{
    *L = (struct Node *)malloc(sizeof(Node));
};

My problem is, wherever I used the (->), I will got this error

error: invalid use of undefined type ...

the compiler mark the error at any (->) in my code. For example:

int isEmpty(List L)
{
    return (L->Next == 0);
};

will get the error at (->).

I know my code is so dump. Please help me. Thanks.

  • 3
    `struct {` is an anonymous struct. You want `struct Node {` – UnholySheep Oct 14 '22 at 09:08
  • 2
    Slightly off topic: first of all please do't use pointless `typedefs` that hide pointer types, it makes your coe less readable. Like in `typedef struct Node *Position;` – Jabberwocky Oct 14 '22 at 09:08
  • 1
    `struct { } Node;` does not define a type `struct Node`. It defines a variable `Node` of an anonymous struct type. Even if it did define `struct Node` you would need to define it before you can use `struct Node*Next` in your struct. Use `struct Node { };` as mentioned above – Gerhardh Oct 14 '22 at 09:10
  • You probably want `struct Node { Element Data; struct Node *Next; };` instead of `struct { Element Data; struct Node *Next; } Node;` In latter case you declare variable `Node` that has an anonymous struct type. – Jabberwocky Oct 14 '22 at 09:11
  • `typedef struct Node *Position; typedef Position List;` It is generally not the best idea to hide pointer types in a typedef. Also what is the added value of defining an alias `List` for type `Position`? Either you have a dedicated type for a whole list (with more than just a head pointer or you can just stick with the nodes type – Gerhardh Oct 14 '22 at 09:31

2 Answers2

0

In general, the first declaration of struct Node is not correct. If you specify the name of the structure at the end of its declaration, you are not specifying data type, but you create only the struct variable. Therefore, the compiler doesn't know how to allocate struct Node *Next; item in your struct.

You can simply repair your code by moving the name of the structure:

typedef int Element;
struct Node
{
    Element Data;
    struct Node *Next;
};

typedef struct Node* Position;
typedef Position List;
  • @Gerhardh That is definitely true... – Peter Janků Oct 14 '22 at 09:28
  • Sorry, that comment should go to the question, not below your answer. No idea how it ended up here.... Big fingers.... ;) – Gerhardh Oct 14 '22 at 09:31
  • There is no *first* declaration of type `struct Node` in the OP's code, correct or incorrect, because there isn't *any* declaration of that type. Unless you mean the implicit forward declaration arising from the member declaration `struct Node *next`. Which is not a problem for allocating a `struct Node *`, nor is that what the compiler complains about. The issue is that without a definition of `struct Node`, it does not know how to *dereference* pointers of that type. – John Bollinger Oct 14 '22 at 13:47
  • @JohnBollinger Well, you are 100% correct. My answer was hurried. Next time will think one more time before posting the answer. – Peter Janků Oct 14 '22 at 17:38
0

My problem is, wherever I used the (->), I will got this error

Your struct needs to be defined as a type and at the same time a self-referencing type, able to point at a variable which is of the same type as itself. In can be done like this:

typedef struct Node
{
  Element Data;
  struct Node *Next;
} Node;

Where the first Node is a struct tag, which is a name allowed to co-exist with the type name Node later defined at the } Node;.


Hiding pointers behind a typdef like typedef struct Node *Position; is horrible practice, because it achieves nothing except making the code much harder to read for everyone including yourself. There's no need for a typedef at all here, just declare a variable Node* Position.

Similarly, drop the typedef Position List;, creating new types just for the heck of it only creates clutter.


This is how I initialize this Struct (i dont know if this function is wrong):

The reason why you aren't sure, is because of all the obscure typedefs. Consider rewriting the function as:

void resetList (Node** list)
{
  *list = malloc(sizeof(Node));
};

The reason why it has to be a pointer-to-pointer is explained here: Dynamic memory access only works inside function

As for what this function does, resetList is a very weird name for a function allocating a single node. I would expect it to delete the previous list if present and then maybe allocate a new node.

Lundin
  • 195,001
  • 40
  • 254
  • 396