PUN...TERO!


LinceAzul

Tu lince confiable
Noderador
Nodero
Noder
Pues me siento inspirado y os voy a dar la lata un poquito con algunas explicaciones y dibujos pochos en paint.
Pun...teros? Pun-teros. PUNTEROS.

AVISO: Esto no es una clase de FUNDAMENTOS, por lo que tienes que tener algo de idea de progra para entender esto ya que voy a mencionar listas enlazadas, direcciones de memoria, etcetcetc. Por lo que si no sabes ni lo que es una estructura de datos, ten en cuenta que puede que no entiendas una puta mierda. Dicho esto, seguimos.
Antes de nada, tengo que deciros que todo esto va a estar explicado en
C, pero si tienes una ligera idea de programación, puedes hacerte una idea de qué coño hablo.

Qué coño es un puntero? Pues literalmente es algo que apunta, sin más. Te explico, la ventaja de C es que no es tan de alto nivel, por lo que puedes jugar con direcciones de memoria, registros y polladas del estilo.

Un puntero es una variable que apunta a otra. Puedo tener punteros que apuntan a enteros, a chars, a a putos arrays, a estructuras y básicamente a lo que me salga de los cojones.

El asterisco es la forma de decir que una variable es un puntero. Ejemplo:
C:
int *puta
C:
int puta
La diferencia en dibujito es básicamente esto:
1678485482639.png

Tenemos dos putas, sólo que la roja es un entero sin más y la azul es un puntero que apunta a un entero. La cosa es, ¿cómo lo apunta? Sencillo. Las variables tienen direcciones de memoria (numero pequeño de arriba). Pues el valor del puntero, es la dirección de memoria a la que apunta. En este caso el valor del puntero puta es 111, por lo que apunta a la dirección 111, donde está guardado el número 69.

La cosa eeees, esto tiene más utilidad a parte de apuntar a enteritos y a chars. Aquí es donde entran las STRUCTS.

Si tenéis un ligero conocimiento de estructuras de datos, conoceréis lo que es una lista enlazada. Pues bien, aquí usando C la veremos con PUN...TEROS.
( Sólo un par de cosillas, no os motivéis).

Pues, imaginemos los siguientes datos:
C:
typedef struct NodeNum *ListNum;
struct NodeNum {
    int num;
    ListNum ptrNext;
};
Siendo "ListNum", un puntero a la estructura "NodeNum". Por ahora lo mismo que antes, sólo que en vez de con int, con estructuras.

Para que veais mejor, disfrutad de la siguiente obra de arte:
1678486181067.png

Lo de arriba a la derecha son dos formas de dibujar que un puntero apunta a nulo. Esto tiene utilidades como para ver si una lista está vacía o para iterar sobre ella, etcetcetc.
Teniendo en rojo un ejemplo concreto de una lista enlazada con los datos números "4 2 y 0"

Bueno que sí, ¿pero cómo coño aplico esto? Porque habrá un momento en el que tendré que usar funciones para crear, eliminar, insertar elementos de la lista. Pues os voy a introducir el concepto del malloc y cómo acceder al valor de un puntero.

malloc pide memoria simplemente. La pide dependiendo de lo que tú le pongas. Puedes poner exactamente el número de bytes que quieres coger, tipo 1, 2, 3,... O si no sabes el número concreto (por ejemplo, un entero suele tener 2 bytes), pues usas la función sizeof() (te devuelve el tamaño en bytes de lo que le pases como parámetro).
Ejemplo: malloc(sizeof(int)); He pedido con malloc un bloque con el tamaño de un entero.
Luego esto se lo puedo asignar a punteros. Imagina que tengo ListNum ptrH. si lo igualo a malloc(sizeof(int)) el puntero ese apunta a un bloque del tamaño de un entero. Si lo piensas, no me sirve de nada, porque ptrH apunta a un Nodo, y el tamaño de un entero no es el mismo que el tamaño de la estructura nodo, por lo que haríamos lo siguiente: malloc(sizeof(struct NodeNum));

Empecemos sencillito, luego te aplico el malloc. Si me quiero crear una lista vacía, simplemente pongo el puntero a nulo, sin más, no tiene más misterio
C:
void create(ListNum *ptrH){
    (*ptrH) = NULL;
}
Pongo paréntesis porque C es muy tocapelotas y especialito y a veces da castañazos por la puta cara si no se lo das todo como si fuera gilipollas.
Tengo un puntero que apunta a un puntero que apunta a una estructura Nodo. Accedo a lo que apunta un puntero con el asterisco.

Entonces, debería hacer (*ptrH) para acceder a lo que apunta ptrH, y ya en ese puntero, modifico lo que apunta. En dibujito, con *ptrH accedo a lo de dentro del círculo rojo, sin eso, accedo a lo de dentro del círculo azul.

1678487383796.png


Pero, no entiendo, cuál es el punto de que *ptrH apunte a nulo, si yo quiero una estructura vacía no? no que apunte a la nada. Correcto, la gracia es que lo dejas así para que luego ya hagas tus mallocs necesarios para insertar elementos y cositas del estilo.

Vale, ahora otra cosa nueva. Cómo apunto a valores dentro de la estructura apuntada por un puntero?? Pues literalmente con flechitas (también se puede con puntos, pero hasta el mismo cLion te lo corrije a flechita).

Dicho esto, cómo inserto un valor en una lista?? Asumimos que al insertar, lo insertamos al principio y quedaría algo así:

C:
void insert(ListNum *ptrH, int v){
    ListNum ptrAux = NULL;
    ptrAux = (ListNum) malloc(sizeof(struct NodeNum));
    ptrAux -> num = v;
    ptrAux -> ptrNext = (*ptrH);
    (*ptrH) = ptrAux;
}

Aquí viene la cosa importante. CUIDADO con que los punteros no apunten a cuenca. Me explico, si directamente meto un nodo al principio y digo: 1º Puntero cabeza apunta al nodo nuevo y nodo nuevo apunta al nodo apuntado antes por la cabeza SE ME LÍA.
Porque si el puntero cabeza apunta al nuevo nodo, el resto de la lista que estaba apuntado por el puntero cabeza, la pierdo en el infinito y más allá, ya que no está apuntada por nada más y no tengo manera de volver a apuntarlo. Por ese motivo me creo un puto puntero auxiliar, PARA NO PERDER NADA.

Imagínate que tengo una lista de 2 elementos y quiero meter el "3" al principio, visto en dibujito se vería tal que así:



1678488434083.png

1º creo el nodo nuevo apuntado por ptrAux. 2º le metro el valor 3 y hago que apunte al que era antes el 1º(la cabeza). 3º una vez hecho esto, puedo cambiar *ptrH sin miedo a perder nada, por lo que lo apunto al que es el nuevo nodo cabeza (el que tiene el 3) 4º al acabar la función, el aux se borra y se te queda la listita nueva.

Me da mucho palo escribir más, ya me aburro, pero espero que hayáis aprendido un concepto nuevo. Lo que sea pregunten por los comentarios, que el concepto de puntero al principio es rarete.
 

Dark

🔥root313🔥
Staff
Moderador
Paladín de Nodo
Jinete de Nodo
Burgués de Nodo
Noderador
Nodero
Noder Pro
Noder
Pues me siento inspirado y os voy a dar la lata un poquito con algunas explicaciones y dibujos pochos en paint.
Pun...teros? Pun-teros. PUNTEROS.

AVISO: Esto no es una clase de FUNDAMENTOS, por lo que tienes que tener algo de idea de progra para entender esto ya que voy a mencionar listas enlazadas, direcciones de memoria, etcetcetc. Por lo que si no sabes ni lo que es una estructura de datos, ten en cuenta que puede que no entiendas una puta mierda. Dicho esto, seguimos.
Antes de nada, tengo que deciros que todo esto va a estar explicado en
C, pero si tienes una ligera idea de programación, puedes hacerte una idea de qué coño hablo.

Qué coño es un puntero? Pues literalmente es algo que apunta, sin más. Te explico, la ventaja de C es que no es tan de alto nivel, por lo que puedes jugar con direcciones de memoria, registros y polladas del estilo.

Un puntero es una variable que apunta a otra. Puedo tener punteros que apuntan a enteros, a chars, a a putos arrays, a estructuras y básicamente a lo que me salga de los cojones.

El asterisco es la forma de decir que una variable es un puntero. Ejemplo:
C:
int *puta
C:
int puta
La diferencia en dibujito es básicamente esto:
Ver el archivo adjunto 22718
Tenemos dos putas, sólo que la roja es un entero sin más y la azul es un puntero que apunta a un entero. La cosa es, ¿cómo lo apunta? Sencillo. Las variables tienen direcciones de memoria (numero pequeño de arriba). Pues el valor del puntero, es la dirección de memoria a la que apunta. En este caso el valor del puntero puta es 111, por lo que apunta a la dirección 111, donde está guardado el número 69.

La cosa eeees, esto tiene más utilidad a parte de apuntar a enteritos y a chars. Aquí es donde entran las STRUCTS.

Si tenéis un ligero conocimiento de estructuras de datos, conoceréis lo que es una lista enlazada. Pues bien, aquí usando C la veremos con PUN...TEROS.
( Sólo un par de cosillas, no os motivéis).

Pues, imaginemos los siguientes datos:
C:
typedef struct NodeNum *ListNum;
struct NodeNum {
    int num;
    ListNum ptrNext;
};
Siendo "ListNum", un puntero a la estructura "NodeNum". Por ahora lo mismo que antes, sólo que en vez de con int, con estructuras.

Para que veais mejor, disfrutad de la siguiente obra de arte:
Ver el archivo adjunto 22719

Lo de arriba a la derecha son dos formas de dibujar que un puntero apunta a nulo. Esto tiene utilidades como para ver si una lista está vacía o para iterar sobre ella, etcetcetc.
Teniendo en rojo un ejemplo concreto de una lista enlazada con los datos números "4 2 y 0"

Bueno que sí, ¿pero cómo coño aplico esto? Porque habrá un momento en el que tendré que usar funciones para crear, eliminar, insertar elementos de la lista. Pues os voy a introducir el concepto del malloc y cómo acceder al valor de un puntero.

malloc pide memoria simplemente. La pide dependiendo de lo que tú le pongas. Puedes poner exactamente el número de bytes que quieres coger, tipo 1, 2, 3,... O si no sabes el número concreto (por ejemplo, un entero suele tener 2 bytes), pues usas la función sizeof() (te devuelve el tamaño en bytes de lo que le pases como parámetro).
Ejemplo: malloc(sizeof(int)); He pedido con malloc un bloque con el tamaño de un entero.
Luego esto se lo puedo asignar a punteros. Imagina que tengo ListNum ptrH. si lo igualo a malloc(sizeof(int)) el puntero ese apunta a un bloque del tamaño de un entero. Si lo piensas, no me sirve de nada, porque ptrH apunta a un Nodo, y el tamaño de un entero no es el mismo que el tamaño de la estructura nodo, por lo que haríamos lo siguiente: malloc(sizeof(struct NodeNum));

Empecemos sencillito, luego te aplico el malloc. Si me quiero crear una lista vacía, simplemente pongo el puntero a nulo, sin más, no tiene más misterio
C:
void create(ListNum *ptrH){
    (*ptrH) = NULL;
}
Pongo paréntesis porque C es muy tocapelotas y especialito y a veces da castañazos por la puta cara si no se lo das todo como si fuera gilipollas.
Tengo un puntero que apunta a un puntero que apunta a una estructura Nodo. Accedo a lo que apunta un puntero con el asterisco.

Entonces, debería hacer (*ptrH) para acceder a lo que apunta ptrH, y ya en ese puntero, modifico lo que apunta. En dibujito, con *ptrH accedo a lo de dentro del círculo rojo, sin eso, accedo a lo de dentro del círculo azul.

Ver el archivo adjunto 22720

Pero, no entiendo, cuál es el punto de que *ptrH apunte a nulo, si yo quiero una estructura vacía no? no que apunte a la nada. Correcto, la gracia es que lo dejas así para que luego ya hagas tus mallocs necesarios para insertar elementos y cositas del estilo.

Vale, ahora otra cosa nueva. Cómo apunto a valores dentro de la estructura apuntada por un puntero?? Pues literalmente con flechitas (también se puede con puntos, pero hasta el mismo cLion te lo corrije a flechita).

Dicho esto, cómo inserto un valor en una lista?? Asumimos que al insertar, lo insertamos al principio y quedaría algo así:

C:
void insert(ListNum *ptrH, int v){
    ListNum ptrAux = NULL;
    ptrAux = (ListNum) malloc(sizeof(struct NodeNum));
    ptrAux -> num = v;
    ptrAux -> ptrNext = (*ptrH);
    (*ptrH) = ptrAux;
}

Aquí viene la cosa importante. CUIDADO con que los punteros no apunten a cuenca. Me explico, si directamente meto un nodo al principio y digo: 1º Puntero cabeza apunta al nodo nuevo y nodo nuevo apunta al nodo apuntado antes por la cabeza SE ME LÍA.
Porque si el puntero cabeza apunta al nuevo nodo, el resto de la lista que estaba apuntado por el puntero cabeza, la pierdo en el infinito y más allá, ya que no está apuntada por nada más y no tengo manera de volver a apuntarlo. Por ese motivo me creo un puto puntero auxiliar, PARA NO PERDER NADA.

Imagínate que tengo una lista de 2 elementos y quiero meter el "3" al principio, visto en dibujito se vería tal que así:



Ver el archivo adjunto 22721
1º creo el nodo nuevo apuntado por ptrAux. 2º le metro el valor 3 y hago que apunte al que era antes el 1º(la cabeza). 3º una vez hecho esto, puedo cambiar *ptrH sin miedo a perder nada, por lo que lo apunto al que es el nuevo nodo cabeza (el que tiene el 3) 4º al acabar la función, el aux se borra y se te queda la listita nueva.

Me da mucho palo escribir más, ya me aburro, pero espero que hayáis aprendido un concepto nuevo. Lo que sea pregunten por los comentarios, que el concepto de puntero al principio es rarete.
No se que coño es nada de esto pero me molan los posts de programación.
 
  • Fueguito
Reacciones : usuario1991

obtuso

5g causa cancer
Burgués de Nodo
Noderador
Nodero
Noder
nadie sabe lo que son los punteros, solo hace que lo sabe y funciona porque ezequiel quiere
 
  • Viva España
Reacciones : LinceAzul

Rodkaiser

Més que un nodero
Noderador
Nodero
Noder
Si esto se considera programación, no quiero programar nunca en mi vida
Mientras no programes en C/C++ o Rust no te tienes que preocupar. Python y Java utilizan punteros pero es transparente al programador, es decir que te la suda porque lo hace solo y no tienes ni que saber qué son.
 
  • Like
Reacciones : usuario1991