Asignación de memoria dinámica para el nodo en la lista vinculada

Aug 20 2020

¿Por qué cuando tengo que declarar un puntero a un nodo (cabeza) también tengo que asignar memoria con malloco callocpara él? Vi que el código que genera una lista (no importado aquí) funciona bien también sin asignarle memoria y simplemente declarando node *head.

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

int main(){

    node *head;

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

¿Y por qué cuando asigno memoria como arriba tengo que escribir (node*)? ¿No está ya asignado a un nodo de estructura ya que lo estoy haciendo en la cabeza? ¿Cuál es exactamente el significado de esa línea de código? Además, cuando escribo, head = NULL¿configuro la dirección de la cabeza del puntero en NULL o qué?

Respuestas

2 VladfromMoscow Aug 19 2020 at 23:35

Este fragmento de código

node *head;

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

produce una pérdida de memoria.

Al principio nodese asignó una memoria para un objeto del tipo y su dirección se asignó al punterohead

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

e inmediatamente se sobrescribió el valor del puntero.

head = NULL;

Como resultado, la dirección de la memoria asignada se perdió y la memoria asignada no se puede liberar.

El fragmento de código no tiene ningún sentido. Bastará con escribir

node *head = NULL;

En este caso, inicialmente tendrá una lista vacía.

¿Y por qué cuando asigno memoria como arriba tengo que escribir (nodo *)?

La función mallocdevuelve un puntero del tipo void *. Se void *puede asignar un puntero de este tipo a un puntero de cualquier otro tipo de objeto. Entonces en C el casting es redundante.

En C ++ tienes que lanzar explícitamente un puntero del tipo void *al tipo del puntero de objeto al que void *está asignado el puntero del tipo .

Además, cuando escribo head = NULL, ¿configuro la dirección de la cabeza del puntero en NULL o qué?

No estableció la dirección del puntero en sí. El puntero fue asignado por el compilador y tiene la duración de almacenamiento automático. Establece el valor de la variable headque tiene el tipo node *en NULL.

2 rici Aug 19 2020 at 23:43

En C, los punteros son valores, al igual que los números enteros. Cuando escribes:

int a;
a = 3;

almacena el valor 3 en la variable a.

Cuando escribes:

int* p;
p = NULL;

almacena el valor NULLen la variable p. Los punteros no tienen nada de especial. La asignación no depende en modo alguno del valor de p, es decir, de lo que podría o no señalar. (En este caso, no apunta a nada, pero eso es irrelevante).

mallocdevuelve un puntero a una región de memoria, que como se discutió anteriormente es un valor. El puntero no tiene metadatos intrínsecos; mallocno requiere ninguna información más allá del tamaño de la región de memoria. En particular, no sabe (ni le importa) para qué se utilizará la región de memoria. Una vez que se produce ese valor, puede manejarlo como mejor le parezca, por ejemplo:

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

Dado que pse declara como un puntero a an int, se espera que la memoria apuntada por ppueda contener un int. (Aún no lo hace, pero podría hacerlo). Pero puede pasar el puntero (como un valor) sin que tenga ningún efecto sobre el entero (si lo hay) almacenado en la memoria apuntada. Por ejemplo, después

int* q = p;

qy papuntar a la misma memoria.

Si encuentra algo de esto confuso, probablemente sea porque espera que un puntero sea algo más que un valor simple. Sin embargo, son valores simples y necesitas un modelo mental que se base en esa simple realidad.