0

This a follow up from this question: Why does a function which returns void not hold value?. A user indeed suggested me to draw the pointers in the function struct node * insert_front and so the main questions is about that function and this line of code head = new

This is the minimum code needed:

#include <stdio.h>
#include <stdlib.h>

struct node {
    int value;
    struct node* next;
};

struct node* init(int value) {
    struct node* head = malloc(sizeof(struct node));
    if (!head) return NULL;
    head->value = value;
    head->next = NULL;
    return head;
}

void insert_back(struct node* head, int value) {
    if (!head) return;
    struct node* temp = head;
    struct node* new = malloc(sizeof(struct node));

    while (temp->next != NULL) {
        temp = temp->next;
    }

    temp->next = new;
    new->value = value;
    new->next = NULL;
    return;
}

struct node* insert_front(struct node* head, int value) {
    struct node* new = (struct node*)malloc(sizeof(struct node));
 
    new->value = value;
    new->next = head;
    printf("head->value: %d\n", head->value);
    printf("head->value ptr: %p\n", &head->value);
    printf("new->value: %d\n", new->value);
    printf("new->value ptr: %p\n", &new->value);
    
    head = new; 
    printf("head->value: %d\n", head->value);
    printf("head->value ptr: %p\n", &head->value);
    printf("new->value: %d\n", new->value);
    printf("new->value ptr: %p\n", &new->value);

    return new;
}

int main() {
    struct node* head = init(5);
    insert_back(head, 7);
    insert_back(head, 9);
    insert_back(head, 12);
    head = insert_front(head, 999)
return 1;
}

The output produced from struct node* insert front(...) is

    // after, new->next = head 
    head->value: 5
    head->value ptr: 0x(...)9e0
    new->value: 999
    new->value ptr: 0x(...)a50

    // after, head = new 
    head->value: 999
    head->value ptr: 0x(...)a50
    new->value: 999
    new->value ptr: 0x(...)a50

So we see that after head = new we have the same addresses for head and new. Given this I have two questions.

Firstly, have I understood correctly that, after head = new what happens is that we have moved the pointer which was pointing to the start of that region of memory used by the linked list (that is from head) to a new place in memory (that is where new is in memory)? Otherwise (or more technically, well-explained) what happened?

Secondly, when I print:

printf("&head->value: %p\n", &head->value);
printf("&head: %p\n", &head);
printf("head: %p\n", head);

I obtain

&head->value: 0x(...)9e0
&head: 0x(...)8c8
head: 0x(...)9e0

So, with head I am accessing the address of the region of memory I am pointing to and with &head the address of the pointer itself. But then why with &head->value I am accessing the same as with head?

  • 2
    `&head->value` is `&(head->value)`, it is the address of `head->value`, not `head`. – mch Nov 05 '21 at 09:30
  • 1
    Read up on [operator precedence in C](https://en.cppreference.com/w/c/language/operator_precedence). – paddy Nov 05 '21 at 09:31
  • Alright, thanks, it makes sense now. What about the first part of the question? – bugs_and_stars Nov 05 '21 at 09:34
  • 2
    Linked list doesn't occupy a "region of memory". Every node on its own occupies it's own "region", so the list as a whole is a chain of tiny regions, each living on their own. Pointer is exactly what the word says - it points. So `head = new` makes `head` point same place `new` points . `new` is not "in memory" in this meaning. `new` points to memory "region" you've got from `malloc`. And now `head` points there as well. If you print the pointer, you get the numeric address of a memory cell. That's what the pointer really is - an integer value. You can think it's an `id` of a memory cell. – Agent_L Nov 05 '21 at 09:53
  • 1
    This clarified many things, especially that 'Linked list doesn't occupy a "region of memory". Every node on its own occupies it's own "region", so the list as a whole is a chain of tiny regions'. Thanks – bugs_and_stars Nov 05 '21 at 10:01

1 Answers1

2

Firstly, have I understood correctly that, after head = new what happens is that we have moved the pointer which was pointing to the start of that region of memory used by the linked list (that is from head) to a new place in memory (that is where new is in memory)? Otherwise (or more technically, well-explained) what happened?

head = new does not move head. It changes the value of head. head is a pointer; its value is a memory address.

But then why with &head->value I am accessing the same as with head?

With C’s grammar, &head->value is &(head->value), not (&head)->value. It uses head to locate head->value and then takes the address of that. It does not take the address of head and then use it as a pointer to a structure.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312