Search code examples
cpointersstructdynamic-memory-allocationtype-safety

What happens to this struct pointer?


I'm using the following code to push a new node at the front of the linked list. I have some doubts regarding some concepts.

void push(struct node **head, int data)
{
    // create a new node
    struct node *new_node;
    new_node = malloc(sizeof(struct node));

    // add data
    new_node->data = data;

    // add node to front of list
    new_node->next = *head;
    *head = new_node;
}
  1. When I assign the value of new_node to *head in *head = new_node, and then return, does the pointer new_node get destroyed, as it's an automatic variable?

  2. Should the memory pointer by new_node, assigned to it by the malloc call still be legal to access after new_node is destroyed, as it's on the heap, and was never de-allocated?

  3. We're just using the new_node as a placeholder to store an address to some memory, and after we're done with the assignments and stuff, we let it go. Then should it matter that new_node is of type struct node, for all pointers are just integers, and we're just using it to store a memory address. Where does the pointer type become relevant i.e. why do I have to declare the data type of the pointer to match the pointee's datatype?

  4. Can I just declare all pointers as integers and then explicitly typecast them before using, to match the pointee's datatype?


Solution

  • for all pointers are just integers, and we're just using it to store a memory address.

    No! Pointers are just address locations in memory and their size depends on the compiler and the architecture used. There's no guarantee by language that they are integers.

    Where does the pointer type become relevant i.e. why do I have to declare the data type of the pointer to match the pointee's datatype?

    Type safety. When you've a pointer to a character, it would be of type char*, but casting it into an integer pointer and writing to it may lead to memory corruption. Let me show you an example

    char ch = 'a';
    char *cp = &ch;
    int *ip = (int*) cp;   // type safety lost since the pointer no longer refers to just one character
    *ip = 1000;    // memory to which 1000 is written to would span beyond a character's size
    

    When *ip = 1000 is seen by the compiler, it has no way of warning you against this corruption since it believes that the underlying pointee is an integer; an integer can of course hold 1000 and thus compiles it fine; had it been *cp = 1000 this value would be implicitly converted into a value hold-able by a char and thus no memory corruption by it. Also if you'd enabled warnings the compiler will be able to warn you of this narrowing implicit conversion. GCC spits warning: overflow in implicit constant conversion.

    Can I just declare all pointers as integers and then explicitly typecast them before using, to match the pointee's datatype?

    You certainly can, but don't, for the above reason. Read more about type safety.