Consulta sobre punteros y doble punteros

Iniciado por palacio29, 17 Mayo 2019, 16:35 PM

0 Miembros y 1 Visitante están viendo este tema.

palacio29

Tengo una consulta con el siguiente codigo:

Entiendo que cuando pongo char*Str=NULL lo que estoy declarando es un puntero cuyo contenido es NULL.
Lo que no entiendo es cuando str= CARGA().
No entiendo muy bien es  como funciona la siguiente linea "str=CARGA();".
Que es lo que hace esta funcion?.
Entiendo que hace que str= direccion de memoria del otro puntero.
Pero si estoy haciendo eso...no deberia poner *str=CARGA() para que el contenido de mi puntero str sea la direccion de esa memoria?.
Osea que es lo que se guarda en el contenido de STR? y porque con un simple %s sale la frase cuando deberia poner un asterisco?..

#include <stdio.h>
#include <stdlib.h>
char*CARGA();
void CARGA2(char**);
int main()
{
    char *str=NULL;
    str=CARGA();
    CARGA2(&str);
    printf("\n%s",str);
    return 0;
}
char*CARGA()
{
    char*texto=NULL;
    int i=0;
    char letra;
    texto=malloc(sizeof(char));
    letra=getche();
    while(letra!='\r')
    {

        *(texto+i)=letra;
        i++;
        texto=realloc(texto,(i+1)*sizeof(char));
        letra=getche();
    }
    *(texto+i)='\0';
    return texto;
}


MAFUS

Una cadena no devuelve su contenido sino su dirección de memoria. Pues eso mismo hace la función: regresa la dirección de memoria de la primera letra de la cadena. Como es una dirección de memoria lo debe adquirir el puntero (por tanto no se va a pasar su contenido).

printf ya sabe que con %s el parámetro va a ser una cadena e internamente va a hacer lo necesario para mostrarla. Pero otra vez a una cadena se le accede por medio de su dirección de memoria del primer elemento, no por su contenido, así que no necesita el *.

palacio29

Hay algo que no entiendo  en la parte de str=carga()...esa duda si que no la entiendo.
Supongamos que declaro mi puntero char =NULL como en la linea 7 es esta cajita.
Donde 150 es la direccion de memoria de mi puntero y NULL es su contenido.

l NULL l
  ------
   150

En la linea 8 yo pongo que str=CARGA() y CARGA me va a devolver un puntero al texto que cargue.
Entonces segun lo que creo mi caja queda asi?

l Direccion Memoria Del Texto (Primer posicion del texto) l
               --------------------------------
                   150


Entonces al hacer el %s detecta la primera posicion de la direccion de memoria del texto y me imprime el texto?.

@XSStringManolo

#3
Lo que almacenas en la direccion de memoria es un char, que ocupa 1byte.
No se te imprime el texto entero por arte de magia al tener la direccióm de memoria del primer char.

Digamos que tu texto es "hola" el puntero apunta a 0xff0033 en esa direccion de memoria esta la letra h
Entonces para imprimir la letra o, lo que se hace es una operación, direccion de memoria del puntero + 1byte es decir 0xff0033 + 8bits. Que vendria a ser 0xff003A. Como las cadenas de caracteres se guardan en direcciones de memoria contiguas, podemos imprimir todos los chars de la cadena con una operación sencilla. Sería algo así internamente:
Imprimir en pantalla el char dentro de la direccion de memoria a la que apunta el puntero, direccion de memoria del puntero + 8 bits, direccion de memoria del puntero + 16 bits, dirección de memoria del puntero +24 bits.
La dirección de puntero contiene h, la direccion del puntero + 8 bits contiene o, la direccion del puntero +16 bits contiene l, la dirección del pumtero + 24 bits contiene a.

Por si no te queda claro sería algo así:
Imprimir contenido de la dirección de memoria del puntero.
Imprimir contenido de la dirección de memoria +1byte del puntero
Imprimir contenido de la dirección de memoria +2bytes del puntero.
Imprimir contenido de la dirección de memoria+3bytes del puntero.

Como ves es el mismo puntero todo el rato. Con este unico puntero hacemos operaciones con la memoria a la que apunta para acceder al siguiente caracter.
El caracter está en binario, este caracter en binario se transforma en decimal. Y de decimal se transforma en letra. Busca en google tabla ascii y podras ver que valor decimal corresponde a cada letra/caracter. Ese valor al transformarse en binario ocupa los 8 bits.
Puedes incluso poner char miletra =valorDecimal; y se transformara en la letra correspondienteen la tabla ascii. Saber esto sirve para codificar en otras bases. Por ejemplo base64 que se usa mucho.
Busca en google como transformar un string a base64 y veras como tienes que transformar cada caracter en binario y una vez todos en binario se pillan los bits de 6 en 6 en vez de 8 en 8 para conseguir el string en base64.
Podrias hacer un programa que te convierta un texto a base64 para ver como funciona todo y recordarlo.

Recuerda que 1 byte es lo mismo que 8 bits. Estas operaciones podrías realizarlas tu manualmemte con un puntero apuntando al primer caracter de una cadena y sumarle los bits a la direccion de memoria para obtener todo el string con solo un puntero, no es nada complejo. Las funciones, metodos e incluso el compilador realizan muchas de estas tareas por nosotros para facilitarnos el codigo. Espero que me entendieses. Si no, pregunta.

MAFUS

Para que entiendas: NULL es lo mismo que 0, por tanto char *puntero = NULL es lo mismo que char *puntero = 0, es decir, puntero apuntará a la dirección 0 de memoria. C determina que la posición 0 (NULL) siempre será una posición no válida y saltará el error. Se usa por parte del programador para evitar que un puntero apunte a cualquier sitio y crear problemas de seguridad. Mejor que el programa muera a que te quedes sin dinero en el banco porque no has inicializado un puntero.

Las cadenas en C empiezan en una posición x de la memoria y son secuenciales, es decir, sus datos se encuentran en x+0, x+1, x+2, ... hasta que el dato de x+n valga '\0' (eso es 0), notar que he dicho el dato, el valor de la posición de memoria y no la posición de memoria en sí. Por tanto una función que trabaje con cadenas empezará dónde se le indique el puntero que devuelve la cadena y va recorriendo la memoria de forma secuencial hasta encontrar el carácter de fin de cadena, haciendo lo que deba hacer en cada carácter encontrado.