Ayuda con punteros en C

Iniciado por snake_linux, 25 Agosto 2015, 14:07 PM

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

snake_linux

Hola a tod@s, como sabeis estoy aprendiendo C, ya se lo básico pero me he puesto a aprender punteros y estoy hecho un lio, no son pocas las veces que he intentado aprender punteros en C y no lo asimilo ni por a ni por b.

Lo básico de punteros más o menos lo se, se que los punteros se declaran con:


tipo *var;


ej:


int *p;


El caracter & delante de una variable se usa para hayar la dirección de memoria de dicha variable, para después, guardarla en un puntero, ej:


int *p;
int a=5;
p=&a;


Y también se que el caracter * sirve para hayar el valor de lo que apunta un puntero, por ejemplo

int *p;
int a=5;
p=&a;
int b=*p;
printf("el valor de b es: %d\n", b);


Hasta ahí llego, el problema lo tengo en cosas más avanzadas, como cuando leo la relación que hay entre punteros y arrays, no acabo de entenderlo, por ejemplo he escuchado que un array es un puntero pero ya digo no me queda del todo claro como manejarlos.

Por ejemplo, no veo la diferencia entre un


char nombre[10];


de un:


char *nombre;


¿Es lo mismo?

También, si me pudieran explicar un poco los punteros (quitando lo básico que he puesto arriba que se) se lo agradecería muchísimo.

Saludos.

ivancea96

Un array es un puntero. La diferencia es, que en evz de apuntar a 1 variable, apunta a un conjunto de variables, una delante de otra (en memoria).

Cita de: snake_linux en 25 Agosto 2015, 14:07 PM

char nombre[10];
char *nombre;


¿Es lo mismo?

No, no lo es. El primero tiene 10 chars de memoria. El segundo, solo es un puntero.
A nivel práctico sí, ambos son punteros. Pero para utilizar el segundo como puntero, tienes que reservarle memoria:

char *nombre;
nombre = (char*) malloc(sizeof(char) * 10);

Con eso, igualamos el puntero a una dirección de memoria que contiene 10 char.

Para acceder a cada uno, utilizas el operador []:
nombre[5] = 'C';

Si utilizas malloc para reservar memoria, luego tienes que liberarla:
free(nombre);

snake_linux

Cita de: ivancea96 en 25 Agosto 2015, 14:14 PM
Un array es un puntero. La diferencia es, que en evz de apuntar a 1 variable, apunta a un conjunto de variables, una delante de otra (en memoria).

No, no lo es. El primero tiene 10 chars de memoria. El segundo, solo es un puntero.
A nivel práctico sí, ambos son punteros. Pero para utilizar el segundo como puntero, tienes que reservarle memoria:

char *nombre;
nombre = (char*) malloc(sizeof(char) * 10);

Con eso, igualamos el puntero a una dirección de memoria que contiene 10 char.

Para acceder a cada uno, utilizas el operador []:
nombre[5] = 'C';

Si utilizas malloc para reservar memoria, luego tienes que liberarla:
free(nombre);

Entonces, una vez que has reservado la memoria necesaria para el char *, la única diferencia entré eso y crear un array de la manera clásica de char nombre[valor] es que la primera forma, se hace con memoria dinámica, por lo que puedo liberar ese espacio cuando quiera y además puedo incluso (por lo que he leido investigando) redimensionarlo sin perder los datos que tenía. ¿ Es así ?.

Aparte de lo que he puesto que se en el post, y junto con esto, ¿ No hay nada más sobre punteros ? Es que estoy investigando por internet de allí y allá y como veo la info "a cachos" no me entero.

Saludos y gracias.

ivancea96

Los punteros realmente, solo es eso, un apuntador a una dirección de memoria. Luego los usas como veas.

Pero sí, en general, pasar variables por referencia, arrays y matrices.

Lo único eso, una matriz:
int **matriz;
matriz = (int**) malloc(sizeof(int*) * 10);
int i;
for(i=0; i<10; i++)
    matriz[i] = (int*) malloc(sizeof(int) * 10);

matriz[1][8] = 66;


Así obtendrías una matriz de 10x10 dinámica. Realmente es lo mismo que un array, pero jugando con tipos. Ya ahí usas los punteros como quieras.

int *****matriz;
Disfruta rellenándolo con una matriz de 5 dimensiones xD

snake_linux

Cita de: ivancea96 en 25 Agosto 2015, 15:45 PM
Los punteros realmente, solo es eso, un apuntador a una dirección de memoria. Luego los usas como veas.

Pero sí, en general, pasar variables por referencia, arrays y matrices.

Lo único eso, una matriz:
int **matriz;
matriz = (int**) malloc(sizeof(int*) * 10);
int i;
for(i=0; i<10; i++)
    matriz[i] = (int*) malloc(sizeof(int) * 10);

matriz[1][8] = 66;


Así obtendrías una matriz de 10x10 dinámica. Realmente es lo mismo que un array, pero jugando con tipos. Ya ahí usas los punteros como quieras.

int *****matriz;
Disfruta rellenándolo con una matriz de 5 dimensiones xD

No me ha quedado claro el código que me has puesto, si con la segunda linea ya reservas espacio para una matriz, ¿ Para que es ese for ?.

Gracas.

Saludos.

kr.chacacreker

Cita de: snake_linux en 25 Agosto 2015, 16:54 PM
No me ha quedado claro el código que me has puesto, si con la segunda linea ya reservas espacio para una matriz, ¿ Para que es ese for ?.

Gracias.

Saludos.
Fijate
Código (cpp) [Seleccionar]
matriz = (int**) malloc(sizeof(int*) * 10); lo que hace es reservar 10 punteros,el (int**) es un cast, una "conversión". Luego en
Código (cpp) [Seleccionar]
int i;
for(i=0; i<10; i++)
    matriz[i] = (int*) malloc(sizeof(int) * 10);

para cada puntero reservado reserva 1 entero.

Eso jodido para quien no ha visto algo de ingeniería inversa ya que lo ves de otro modo, te recomiendo que pases un poco por los tutes de Introducción al ollydbg de ricardo narvaja, No explica punteros pero te das cuenta de algunas cosas por ej: que cada byte de memoria es apuntado por una dirección de memoria.

ivancea96

Una matriz, no es más que un puntero que apunta a un array de punteros.
Así que una vez reservada memoria para el array de punteros, hay que reservar memoria para cada puntero. Eso lo haces con el for.

snake_linux

Cita de: ivancea96 en 25 Agosto 2015, 18:08 PM
Una matriz, no es más que un puntero que apunta a un array de punteros.
Así que una vez reservada memoria para el array de punteros, hay que reservar memoria para cada puntero. Eso lo haces con el for.

Gracias por la aclaración, ya me has resuelto la duda, gracias :)

Mientras

#8
Bueno, yo no soy de usar **, ya que no lo manejo muy bien  :-[

Como se almacena en memoria un array bidimensional ?. En uno unidimensional sé que es secuencial, y que puedo acceder mediante *(p) , *(p+1) ....





ivancea96

Hay algo que no he comentado.

Los punteros son como se ha dicho, todo bien.

PERO:
int a[5][5];
int b[10];


NO se guardan en memoria de la misma manera. Esas variables se guardan en la pila, mientras que las variables llamadas con "malloc()" se almacenan en el "heap". Además, la organización de los datos no es el mismo.

Pero bueno, simplemente saber que cuando creas "int a[5][6]" no es igual que "int **a".