Professional Documents
Culture Documents
Els punteros.
Un puntero siempre proporciona una direccin de memoria, puede, por ejemplo, guardar la
direccin de memoria de una variable, un array, una funcin. Trabajar con direcciones de memoria
facilita medios para acceder a datos que no estan disponibles de otras maneres. Por ejemplo,
modificar el valor de una variable local definida en una funcin desde otra funcin, como se ver
ms adelante.
Observe el siguiente programa, que a parte de ejemplo no sirve para nada ms.
#include <stdio.h>
#include <conio.h>
main()
{
int Var;
int *pVar;
Var = 50;
pVar = &var // pVar guarda la direccin de memoria de var
*pVar = 30; // pone en direccin de memoria apuntada por pVar, o sea a var,
// el valor 30
printf(%d, Var); // escribir el valor 30
}
Suponga el siguiente mapa de memoria para el programa anterior.
Variable
Valor
Direccin
var
50
1004
pVar
1004
1008
La lnia var = 50, com ya sabe, guarda el valor 50 en la casilla de memoria var, que ocupa la
posicin de memoria 1004.
La lnia pVar = &var, guarda en la variable pVar la direccin de memoria ocupada per la variable
var, 1004. & se llama operador de indireccin, y sirve para indicar direccin de memoria de la
variable que precede.
La lnia *pVar = 30, guarda en la posicin de memoria apuntada por pVar (1004) el valor 30. Como
pVar guarda la direccin de memoria de var, lo que hace esta instruccin es cambiar el valor de la
variable var (le pone el valor 30).
3
Entiende ahora la funcin scanf(%d, &var);
Vea este otro ejemplo. Hacer un programa para entrar dos valores desde el teclado y
guardarlos respectivamente en les variables A y B. Estos valores se han de pasar a una
funcin de manera que cuando se vuelva a main() se ha de cumplir que A > B.
#include <stdio.h>
#include <conio.h>
void cambiar (int *pA, int *pB);
main()
{
int A, B;
clrscr();
puts(Entre el valor para variable A : );
scanf(%d, &A);
puts(Entre el valor para la variable B : );
scanf(%d, &B);
cambiar(&A, &B);
printf(%d, %d , A, B);
}
void cambiar(int *pA, int *pB)
{
int Auxiliar;
if (*pB > *pA)
{
Auxiliar = *pA;
*pA = *pB;
*pB = Auxiliar;
}
}
Arrays y punteros.
Si recuerda el tema de arrays, y concretamente la seccin en la qual se habl del paso de
arrays a funciones, se dijo ( y despus se comprob), que cuando se pasa un array a una
funcin, se trabaja sobre el mismo array definido en la funci que llama, no sobre otro array.
Bien, entonces esto, como puede suponer, es porqu se pasa la direccin de memoria que
ocupa el array y no sus valors. Dado que un array es de hecho una variable que referencia una
direccin de memoria, se puede utilizar la notacin puntero para trabajar con arrays,
As por ejemplo, estas dos expressions son lo mismo,
nota[1] = 3; *(nota + 1);
De hecho, nota[1] es una notacin de puntero camuflada, cuando el compilador encuentra
esta sentencia, la traduce a la forma puntero; internamente la mquina no entiende los arrays
pero si los punteros.
Cuando se declara el array Notas[10], Notas no es nada ms que una referencia a una
direccin de memoria a partir de la cual se reserva el espacio suficiente para guardar diez
datos del tipo int. Vea el esquema siguiente:
Notas
1010
1010
1012
1014
1016
1018
1020
Observe como se han numerado las direcciones de dos en dos porqu los datos tipo int
ocupan dos bytes.
Como ya sabe, para referenciar los diferentes elementos de este array se ha de utilitza un
ndice cerrado entre las llaves [].
En el primer ejemplo para referenciar la variable Var a travs de su direccin, se ha hecho lo
siguiente:
pVar = &Var;
*pVar = 20;
Entonces, si Notas referencia una direccin de memoria, para guardar un valor en esta
direccin de memoria se puede utilizar la notacin:
*Notas = 10;
que seria lo mismo que
Notas[0] = 10;
Si se quiere guardar un valor en la segunda posicin del array , se ha de utilitza Notas[1] =
15, o bien
*(Notas + 1) = 15,
Esto es, en la siguiente posicin de memoria apuntada por Notas, poner un 15.
Observacin.
Siguiente posicin significa en este caso dos bytes ms all de posicin Notas, ya que un int
ocupa dos bytes; si el array fuera de datos tipo char, siguiente posicin significaria un byte
ms all; si fuese de datos tipo float, siguiente posicin significaria cuatro bytes ms all.
Recuerde que el nmero de bytes lo decide el compilador, en funcin del tipo de datos del
array.
Continuado con el array Notas, Notas[2] = 21; seria lo mismo que *(Notas+2) = 21, y se
interpretara como, dos posiciones de memoria, despus de Notas poner un 21.
Vea el esquema siguiente par comparar las notaciones array, y sus equivalentes notaciones
puntero.
Notas
Notas+1
Notas+2
Notas+3
10
15
21
43
Notas[0]
Notas[1]
Notas[2]
Notas[3]
char Nombres[5][10];
Nombres[0]
Nombres[1]
Nombres[2]
Nombres[3]
Nombres[4]
1000
1010
1020
1030
1040
P
M
L
A
A
e
a
l
n
n
r
r
u
t
n
e
i
o
a
\0
a
s
n
\0
\0
\o
I
\0
char *Nombres[5];
1000
1005
1011
1017
1023
Nombres[0]
Nombres[1]
Nombres[2]
Nombres[3]
Nombres[4]
P
M
L
A
A
e
a
l
n
n
r
r
u
t
n
e
y
o
a
\0
a
s
n
\0
\0
\0
y
\0
1000
1005
1011
1017
1023
Observe que en la versin de punteros no se utiliza tanta memoria. A la hora de manipular las
cadenes, tambin resulta ms prctico y rpido utilizar las referncias a las cadenas del array
de punteros. Por ejemplo, al ordenar un array es ms sencillo intercambiar los valors de los
punteros que no cambiar todos los caracteres que forman las cadenas. Resulta ms eficiente
intercanviar los punteros del primer y tercer elementos del array de punteros, que no mover
todos los caracteres de la primera cadena hacia la tercera. Vea el programa siguiente, que
ordena las cadenes, y observe el esquema para comprendre lo qu pasa.
#include <stdio.h>
#include <conio.h>
#include <string.h>
void Ordenar_Seleccion (char *Nombres[]);
main()
{
char *Nombres[5] = {Pere,Maria,Llus,Antoni,Anna};
int y;
Ordenar_Seleccin(Nombres);
for( y=0 ; y < 5 ; y++)
printf(%s \n , Nombres[y]);
}
8
void Ordenar_Seleccion(char *Nombres[])
{
char *pAux;
int y,k, posicin;
Nombres[0]
Nombres[1]
Nombres[2]
Nombres[3]
Nombres[4]
P
M
L
A
A
e
a
l
n
n
r
r
u
t
n
e
y
o
a
\0
a
s
n
\0
\0
\0
i
\0
1000
1005
1011
1017
1023
Var = 10;
*pVar = Var;
*pVar = 20; // Direccin de memoria apuntada por pVar (variable Var), poner un 20
printf(%d, Var);
// Imprimir 20;
printf(%d, Var);
// Imprimir un 30
Es realmente rebuscado, pero hay situaciones (es posible que nunca las encuentre, y si
encuentra una desear no haberla encontrado) que slo pueden resolverse utilizando este tipo
de notacin.
Vea a continuacin un ejemplo de utilizacin de punteros a punteros, Los arrays
bidimensionales.
Primeramente recuerde que un array bidimensional no es ms que un array de arrays.
Suponga un array de int declarado como sigue:
int Tabla[5][5];
1
6
11
16
21
2
7
12
17
22
3
8
13
18
23
4
9
14
19
24
5
10
15
20
25
Tabla[5][5], significa un array formado por 5 arrays, cada uno de ellos con 5 datos del tipo
int..
Tabla[0]
Tabla[1]
10
Tabla[2]
11
12
13
14
15
Tabla[3]
16
17
18
19
20
Tabla[4]
21
22
23
24
25
Tabla es la direccin de todo el array, supoga que comienza en la direccin 1000. En un array
de enteros cada elemento ocupa dos bytes, cada fila entonces, empezar 10 bytes despus de
la anterior (5 elementos de cada fila por dos bytes que tiene cada elemento). El compilador
sabe cuantas columnas tiene cada fila del array ya que se le ha indicado en la declaracin.
As, Tabla+1 es la direccin de tabla 1000, ms los bytes que ocupa una fila, 10; Tabla+1
comenzar entonces en la direccin 1010, Tabla+2 en la direccin 1020, Tabla+3 en la
direccin 1040, y Tabla+5 en la direccin 1050.
Ahora que ha visto como referenciar cada una de las filas; vea como se referencia con
notacin puntero, un elemento individual de alguna de las filas.
10
Cogeremos por ejemplo el primer elemento de la segunda fila. Con notacin array la
direccin de este elemento se indica con &Tabla[1][0], con notacin puntero se indica con
*(Tabla+1). Observe que tanto Tabla+1 como *(Tabla+1) hacen referencia a la misma
direccin. Si se suma 1 a Tabla+1, se aaden 10 bytes, y se encuentra Tabla+2, la direccin
del primer elemento de la tercera fila, pero si se suma 1 a *(Tabla+1), se est sumando slo
dos bytes encontrando entonces la direccin del segundo elemento de la segunda fila. La
expresin quedaria *(Tabla+2)+1, y para referenciar el contenido de esta direccin slo hace
falta referenciar con notacin puntero la expresin anterior, o sea Tabla[1][1] =
*(*(Tabla+1)+1). Generalizando :
Tabla[y][j] = *(*(Tabla+y)+j)
Vuelva a leer el apartado anterior y resiga el esquema siguiente:
Tabla
Tabla+1
*(Tabla+1)
*(*(Tabla+1)+1)
1000
1
1002
2
1004
3
1006
4
1008
5
1010
6
1020
11
1030
16
1040
21
1012
7
1022
12
1032
17
1042
22
1014
8
1024
13
1034
18
1044
23
1016
9
1026
14
1036
19
1046
24
1018
10
1028
15
1038
20
1048
25
Punteros a estructuras.
Un puntero a una estructura se declara de la manera siguiente:
struct Alguna_Cosa *pAlguna_Cosa;
Per referenciar una estructura a travs dun puntero ho farem de la manera siguiente:
struct Alumno
{
char Nombre[10];
int Nota;
int Edat;
};
.
.
struct Alumno Estudiante;
struct Alumne *pAlumno;
pAlumno = &Estudiante;// pAlumno apunta a la variable estudiante.
.
.
11
Ya sabemos que para referenciar los diferentes elementos de la estructura se ha de utilizar la
notacin punto,
Estudiante.Nombre
Estudiante.Nota
Estudiante.Edat
Si se quiere utilizar el puntero, no se puede utilizar la notacin punto, pAlumne no es una
estructura, es un puntero a una estructura, y el operador punto requiere una estructura a su
izquierda. Dado que ya sabe que pAlumno apunta a Estudiante, antonces *pAlumno es el
contenido de Estudiante, por tanto, puede referenciar los elementos de la variable Estudiante
de la manera siguiente:
(*pAlumne).Nombres
(*pAlumne).Edat
(*pAlumne).Nota
Ha de utilizar los parntesi para que el operador punto tenga prioridad los otros. Esta
expresi apenas se utiliza ya que C proporciona una expressin ms simple, el operador ->,
una combinaci del signo menos, y el signo menor que, llamado operador flecha. As , para
referenciar los elementos de una estructura a travs de un puntero se ha de escribir de la
manera siguiente:
pAlumne->Nombres
pAlumne->Edat
pAlumne->Nota
Observe el programa siguiente:
#include <stdio.h>
#include <conio.h>
struct Alumno
{
char Nombre[10];
int Edat;
int Nota;
};
main()
{