2

So I am trying to implement a linked list and I have this struct for each of the nodes:

    typedef struct listNode {
        struct listNode *next;
        void *data;
    } NODE;

Previously, I had made a game where the spacecraft struct looked like this:

   typedef struct {
       int height;
       int width;
   } SPACECRAFT;

and I could make a new spacecraft by doing

  SPACECRAFT plyrShip = {
      .width = //someInt;
      .height = //someInt;
  };

Though with the nodes, the variables are pointers and it isn't allowing me to create a new node by doing

  NODE newNode = {
      .*next = null;
      .*data = *data //function has *data as parameter so I can pass it 
                     //into the node
  }

What am I doing wrong?

jxh
  • 69,070
  • 8
  • 110
  • 193
DevReacc
  • 230
  • 1
  • 11
  • 7
    The `*` is part of the _type_, not of the fieldname, so you just initialize `.next`, not `.*next`. Admittedly, the syntax `struct node *next` is confusing in this regard and indeed, many people prefer to write `struct node* next`, to make that clear. – Ctx Nov 17 '17 at 18:33
  • So in that case, the value I set .next to should be a memory address to the next node in the list? Or the node itself? – DevReacc Nov 17 '17 at 18:35
  • The former, for example with NULL if the node has no successor. – Ctx Nov 17 '17 at 18:36
  • Thanks! You should put your answer in the answer box so I can set this question as answered. – DevReacc Nov 17 '17 at 18:41
  • This is too trivial to be saved for the future, I think you can simply delete this question if your problem is solved now. – Ctx Nov 17 '17 at 18:43
  • 2
    I want to also point out that you probably should not be dereferencing `data` when you are setting `newNode.data`. if `data` is a pointer, then passing in that pointer is probably what you want. – Christian Gibbons Nov 17 '17 at 18:44
  • 1
    @Ctx I disagree, `struct node* next, prev;` is actually more confusing because if the `*` belongs to the type, then what is the type of `prev`? – Iharob Al Asimi Nov 17 '17 at 18:48
  • 1
    @IharobAlAsimi Oh, we play trivial pursuit? ;) The type of prev is `struct node`. – Ctx Nov 17 '17 at 18:52
  • I have a follow-up question in the answer comments if yall want to check that out. – DevReacc Nov 17 '17 at 19:08

2 Answers2

2

You have conflated the pointer declaration syntax and the designated initializer syntax. A member field may be declared to be a pointer type. When using designated initializers, just name the field. Also note they are comma separated.

  NODE newNode = {
      .next = null,
      .data = data
  };
jxh
  • 69,070
  • 8
  • 110
  • 193
  • So if I wanted to allocate memory for it on the heap by using malloc what should I be doing? – DevReacc Nov 17 '17 at 18:54
  • `node *newNode = (node*) malloc(sizeof(newNode));` ? – DevReacc Nov 17 '17 at 18:57
  • `node *newNode = malloc(sizeof(*newNode));` – jxh Nov 17 '17 at 19:01
  • It is to my understanding that if malloc is not able to allocate this memory then it returns a null though I'm not exactly sure what it should be returning if it works since it automatically sets it to type `* void` hence why I tried casting it. – DevReacc Nov 17 '17 at 19:06
  • If `malloc` returns `NULL`, then `newNode` becomes `NULL`. Test `newNode == NULL` to decide if `malloc` succeeded. Casting is generally considered the incorrect tool to use in most cases (there are a few exceptions). In the particular case of casting `malloc`, it can hide the fact the prototype is missing, and causes undefined behavior, which would be especially bad on platforms where pointers are wider than `int`. [Don't cast `malloc`.](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – jxh Nov 17 '17 at 19:13
2

Officially, this is called Designated Initializer which was introduced since C99.

First, you should realize pointer types. struct listNode next; is to declare a variable, next, whose type is struct listNode. struct listNode *next is to declare a variable, next, whose type does be a type which points to a value whose type is struct listNode. So you should do it like that.

  NODE newNode = {
  .next = null,
  .data = data
  }

Moreover, this is what structure looks like in memory. You could remember this to eliminate confusion. And this clearly points out why you couldn't do that. (member next in the structure can't be dereferenced individually because of the structure layout here).

|--------------|
| newNode.next | &newNode
|--------------|
| newNode.data |
|--------------|

Updated Response: Check edit Summary.

DevReacc
  • 230
  • 1
  • 11
yenWu
  • 46
  • 5