-1

Why when i have to declare a pointer to a node (head) I also have to allocate memory with malloc or calloc for it? I saw that the code that generate a list (not imported here) works well also without allocate memory for it and just declaring node *head.

typedef struct str_node{
    int data;
    struct str_node *next;
}node;

int main(){

    node *head;

    head = (node*) malloc(sizeof(node));
    head = NULL;

And why when I allocate memory like above i have to write (node*)? Isn't it already allocated to a struct node since I'm doing it on head? What is the meaning of that line of code exactly? Moreover when I write head = NULL am I set the address of the pointer head to NULL or what?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • You don't have to write `(node*)` and many people here strongly recommend that you don't. (It's required in C++, but that's a different language, and in C++ you shouldn't use `malloc` anyway.) – rici Aug 19 '20 at 16:33
  • `(node*)` just cast the result to a pointer to a `node`, `head = NULL` clears the list (sets the root to `NULL` and **should not** be here because the `malloc` return value must be freed using `free`). – Roy Avidan Aug 19 '20 at 16:35
  • See [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Some programmer dude Aug 19 '20 at 16:37
  • Ok but i don't cast the result to a pointer to a node already declaring "head = ...." @רועיאבידן –  Aug 19 '20 at 16:41
  • Yes, that's why @rici said, correctly, that you do not have to do it (in C, not C++). – Roy Avidan Aug 19 '20 at 16:43
  • Why when I buy an envelope do I also have to buy a house to send the letter to? Pointers and allocated memory are different things. If memory is like houses then pointers are like house addresses. If memory is PO boxes then pointers are like PO box numbers. – user253751 Aug 19 '20 at 16:50
  • I posted a long text about this, including a full C program with a test run. And also a discussion about `malloc()` and reasons for using `node*` and `node**`. I believe I should not duplicate it here, so the link is https://stackoverflow.com/a/63479484/11234199 – arfneto Aug 19 '20 at 16:44
  • Oh thank you i didn't see. –  Aug 19 '20 at 16:47
  • I suggest you run the sample program in your machine and look at the alternative linked list structure I posted at the end. It may make things a bit more clear – arfneto Aug 19 '20 at 16:58

3 Answers3

1

This code snippet

node *head;

head = (node*) malloc(sizeof(node));
head = NULL;

produces a memory leak.

At first a memory for an object of the type node was allocated and its address was assigned to the pointer head

head = (node*) malloc(sizeof(node));

and then at once the value of the pointer was overwritten.

head = NULL;

As a result the address of the allocated memory was lost and the allocated memory can not be freed.

The code snippet does not make any sense. It will be enough to write

node *head = NULL;

In this case you will initially have an empty list.

And why when I allocate memory like above i have to write (node*)?

The function malloc returns a pointer of the type void *. A pointer of the type void * can be assigned to a pointer of any other object type. So in C the casting is redundant.

In C++ you have explicitly to cast a pointer of the type void * to the type of the object pointer to which the pointer of the type void * is assigned.

Moreover when I write head = NULL am I set the address of the pointer head to NULL or what?

You did not set the address of the pointer itself. The pointer was allocated by the compiler and has the automatic storage duration. You set the value of the variable head that has the type node * to NULL.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Is it redundant because i already assigned the allocated memory to a node declaring "head = ..." since head is already a node? –  Aug 19 '20 at 16:43
  • @Boninissimo head is a variable of the pointer type node *, Neither object of the type node was created. That is the pointer does not point to any valid object yet. – Vlad from Moscow Aug 19 '20 at 16:45
1

In C, pointers are values, just like integers. When you write:

int a;
a = 3;

you store the value 3 into the variable a.

When you write:

int* p;
p = NULL;

you store the value NULL into the variable p. There is nothing special about pointers. The assignment does not in any way depend on the value of p, i.e. what it might or might not point at. (In this case, it points at nothing, but that's irrelevant.)

malloc returns a pointer to a memory region, which as discussed above is a value. The pointer has no intrinsic metadata; malloc does not require any information beyond the size of the memory region. In particuar, it does not know (or care) what the memory region will be used for. Once that value is produced, you can deal with it as you see fit, for example:

int* p;
p = malloc(sizeof *p);

Since p is declared as a pointer to an int, it is expected that the memory pointed at by p can hold an int. (It doesn't, yet, but it could.) But you can pass around the pointer (as a value) without it having any effect on the integer (if any) stored in the memory pointed to. For example, after

int* q = p;

q and p point at the same memory.

If you find any of this confusing, it is probably because you are expecting a pointer to be something other than a simple value. However, they are simple values and you need a mental model which is based on that simple reality.

rici
  • 234,347
  • 28
  • 237
  • 341
-1

Malloc is used to allocate a block of memory of the specified size i.e. in this case it is (sizeof(node)) which is an 'item' in the linked list. This can be used to allow your linked list to grow.

(node*) is used to allocate the type of memory. Example from GeeksForGeeks

I recommend reading this https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/ It will explain some of the fundamentals.

Finally to answer this "Why when i have to declare a pointer to a node (head) I also have to allocate memory with malloc or calloc for it?".

A pointer points the compiler towards a memory address so when you declare a section of memory using malloc you need to point towards the start of that memory so you can access it (Hence why you need to specify the size so you know how far to read/write).

Peter
  • 1