1

The code doesn't work until I dynamically allocate the memory for pointer C in merge_List function.

If I uncomment list c = (list)malloc(sizeof(Node)); and comment list c;, the code works. I don't know why. Can anyone explain to me? The code is very straightforward, so not much comment. Thank you!

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
   struct Node *next;
   int value;
}Node,*list;
list create_Node()
{  
   list head = (list)malloc(sizeof(Node));
   if(!head) exit(-1);
   list tail = head;
   int len;
   int val;
   printf("Please enter the length of the list:\n ");
   scanf("%d",&len);
   for(int i=0;i<len;i++)
   {
      list new = (list)malloc(sizeof(Node));
      if(!new) exit(-1);
      printf("Please enter the value of the node:\n ");
      scanf(" %d",&val);
      new->value=val;
      tail->next= new; 
      tail =new;
   }
   return head;
}

list merge_list(list a, list b)
{
    if(a==NULL||b==NULL) exit(-1);
    //list c = (list)malloc(sizeof(Node));
    list c;
    list d = c;
    while(a&&b)
    {
       if(a->value<=b->value)
       {
          c->next=a;
          c=a;
          a=a->next;
       }
       else
       {
          c->next = b;
          c=b;
          b=b->next;
       }
     }
     c->next = a?a:b;
     return d;
}
int main() {

   list  l = create_Node();
   l=l->next;
   list j = create_Node();
   j=j->next;
   list n =merge_List(l,j);
   n=n->next;
   while(n)
   {
      printf("%d\n",n->value);
      n=n->next;
  }
  return 0;
}
GBlodgett
  • 12,704
  • 4
  • 31
  • 45
Liu
  • 413
  • 4
  • 11
  • Welcome to Stack Overflow Liu! In the future please tag your question with the language you are writing in. This allows people to find your question :) – GBlodgett Jan 16 '19 at 00:34
  • 4
    Fyi, `merge_List` != `merge_list`. Related, stop hiding pointer types in typedef aliases. It brings absolutely no clarity to this code, and makes it *less* (not more) obvious where things are broken. There are two cases where aliased pointer types are sensible (callback function types and black-box "handle" architectures) and this is neither of those cases. Trust me, you want to *see* those asterisks as you're coding. – WhozCraig Jan 16 '19 at 00:46
  • 1
    Note the discussion in [Is it a good idea to typedef pointers?](https://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers) — the TL;DR version is "No, except perhaps for function pointers". – Jonathan Leffler Jan 16 '19 at 06:24
  • "The code doesn't work until I dynamically allocate the memory for pointer C in merge_List function." Where should the pointer point to if you do not allocate any memory? You dereference `c` in your `while` loop. That doesn't work without having legal memory location. Or do you assume your other option `list c;` will allocate the required memory on the stack? – Gerhardh Jan 16 '19 at 11:44
  • regarding: `typedef struct Node { struct Node *next; int value; }Node,*list;` it is very poor programming practice to hide a pointer in a `typedef` – user3629249 Jan 16 '19 at 21:53
  • WHY?? And how should I normalize it? – Liu Jan 17 '19 at 14:55

1 Answers1

1

It took a bit of inspection, but this is the struct's type is

list {aka struct Node *}

According to the compiler. In other words, list is a pointer, and calling malloc will allocate memory for the pointer.

You did this before in your function create_Node(), on the line right after

list head = (list)malloc(sizeof(Node));

If you don't do this, you're performing actions on an uninitialized pointer, which is undefined behavior and shouldn't work since you don't clearly have a spot in memory you're using.

What malloc specifically does in this context, will allocate the sizeof a Node's bytes, and return a void pointer, which you cast to a list (or Node *). List will no longer be uninitialized and no longer has undefined behaviour, which is why it works.

Daniel
  • 854
  • 7
  • 18
  • 1
    This is a natural result of the code using `typedef struct { ... } Node, *list;`. That means `Node` refers to the struct itself, while `list` refers to a pointer to the struct. It's the same way `typedef int *pint;` makes `pint` mean pointer to `int`. – ShadowRanger Jan 16 '19 at 01:20
  • I have another question, as we know if we dynamically allocate the memory in a function, after the function is done, the memory eliminates. In my code, I created many "new" pointers, then why after the function create_Node(), those Nodes still exist. – Liu Jan 18 '19 at 13:49
  • The memory does not eliminate after the function is done if it's dynamically allocated. You have to manually free it or wait for the end of the program. – Daniel Jan 18 '19 at 17:26