Doubt with C Pointers

Asked

Viewed 110 times

3

I have a chained list, with a single variable that is the date(int). I did this function to delete by value.

lista *head = NULL;

void deletar(int valor) {

    lista *prev, *temp = head;
    if(temp->data == valor) {
        head = temp->prox;
        free(temp);
    } else {
        while(temp->data != valor && temp != NULL) {
            prev = temp;
            temp = temp->prox;
        }
        prev->prox = temp->prox;
        free(temp);
    }
}

But I don’t understand why when I change: prev->prox = temp->prox; for temp = temp->prox; It doesn’t work properly, since prev->prox and temp, have the same memory address. Address: 0x14d3050 and 0x14d3050

1 answer

1


prev and temp are pointers. That is, they are variables, living in their own memory address, whose value is an address to another place in memory.

int x = 5; // variável com o valor 5
int *y = &x; // variável cujo valor é o endereço de memória da variável x
*y = 6; // Atribui o valor 6 no endereço de memória armazenado em y.
        // ou seja, a x. 

prev->prox is equivalent to (*prev).prox. In prev->prox = temp->prox; you’re saying:

  1. Take the value stored in the memory location pointed by prev
  2. That value is a struct which, among other things, has a memory address called prox
  3. Attribute to prox the memory address that is on (*temp).prox

Visually

Initial state:

-- [ prev ] -- [ elemento a excluir ] -- [ prox ]
                          ^
                         temp

Final state:

-- [ prev ] -- [ prox ]

temp > [ elemento a excluir ] 
              

That is, the previous knot will point to the next of temp. Which means the original list will jump the knot to which temp is pointing. You then release the memory area to which temp points to the next line and temp goes out of scope.

Already in temp = temp->prox; you’re making temp point to your next element. In this case you are changing the address to which the variable temp is pointing. It would be the equivalent of doing:

int z = 6;
y = &z;

See that x in which case it remains 5. You have changed the address to which y not the content of x.

Likewise, nothing happens to prev->prox by the fact that you have changed the address to which temp points out. prev->prox is still pointing to the node address you were wanting to delete.

And the worst: temp is now pointing to the next element (right after the element you intended to delete):

On the next line you’re calling free(temp). In that case:

  1. You are releasing memory from the wrong element address
  2. [elemento a excluir]->prox points to an area of memory you released.

Visually

Initial state:

-- [ prev ] -- [ elemento a excluir ] -- [ prox ]
                                            ^
                                           temp

Final state:

-- [ prev ] -- [ elemento que deveria ter sido excluido ] --  


                            
  • So: Prev->Prox , is taking the address of Prev, not of Prev->Prox ? because that was my confusion.

  • prev->prox takes the address of the next element after the previous one. That is, when you find the element to be deleted, temp and prev->prov point to the same memory address (as stated in your question). The confusion is in finding that temp = algo is equivalent to prev->prox = algo, the two pointers are independent even if at a previous moment they were pointing to the same place. It makes sense?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.