Вы находитесь на странице: 1из 16

Puntero (Lenguaje C)

Es una Variable que representa la posicin (en vez del valor) de otro dato, tal
como una variable o un elemento de una formacin. Los punteros son usados
frecuentemente en C y tienen gran cantidad de aplicaciones, por ejemplo,
pueden ser usados para trasvasar informacin entre una funcin y sus puntos
de llamada. En particular proporcionan una forma de devolver varios datos
desde una funcin a travs de los argumentos de la funcin.
Punteros a funciones
float *ptr1; /* ptr apunta a un valor float */
float *mifun(void); /* la funcin mifunc devuelve un
puntero a un valor float */
La declaracin
int (*ptrafuncion((void);
crea un puntero a una funcin que devuelve un entero y la declaracin
float (*ptrafuncion1)(int x, int y);
declara ptrafuncion1 como un puntero a una funcin que devuelve un valor
float y requiere dos
argumentos enteros.

PUNTEROS Y FUNCIONES
La relacin entre los punteros y las funciones , puede verse en tres casos
distintos , podemos pasarle a una funcin un puntero como argumento
(por supuesto si su parmetro es un puntero del mismo tipo ) , pueden
devolver un puntero de cualquier tipo , como ya hemos visto con
malloc() y calloc() , y es posible tambin apuntar a la direccin de la
funcin , en otras palabras , al cdigo en vez de a un dato.
PUNTEROS COMO PARAMETROS DE FUNCIONES .
Supongamos que hemos declarado una estructura , se puede pasar a
una funcin como argumento , de la manera que ya vimos
anteriormente:
struct conjunto {
int a

double b ;
char c[5] ;
} datos

void una_funcion( struct conjunto datos );

Hicimos notar, en su momento, que en este caso la estructura se


copiaba en el stack y as era pasada a la funcin, con el peligro que esto
implicaba, si ella era muy masiva, de agotarlo.
Otra forma equivalente es utilizar un puntero a la estructura :
struct conjunto {
int a

double b ;
char c[5] ;
} *pdatos

void una_funcion( struct conjunto *pdatos ) ;


Con lo que slo ocupo lugar en el stack para pasarle la direccin de la
misma. Luego en la funcin, como todos los miembros de la estructuras
son accesibles por medio del puntero, tengo pleno control de la misma.
Un ejemplo de funciones ya usadas que poseen como parmetros a
punteros son:
scanf(puntero_a_string_de_control , punteros_a_variables)
printf(puntero_a_string_de_control , variables )
En ambas vemos que los strings de control son , como no podra ser de
otro modo , punteros , es decir que los podramos definir fuera de la
funcin y luego pasarselos a ellas :
p_control = "valor : %d " ;
printf( p_control , var ) ;
PUNTEROS COMO RESULTADO DE UNA FUNCION
Las funciones que retornan punteros son por lo general aquellas que
modifican un argumento , que les ha sido pasado por direccin ( por
medio de un puntero ) , devolviendo un puntero a dicho argumento
modificado , las que reservan lugar en el Heap para las variables
dinmicas , retornando un puntero a dicho bloque de memoria .
As podremos declarar funcines del tipo de:
char *funcion1( char * var1 ) ;
double *funcion2(int i , double j , char *k ) ;

struct item *funcion3( struct stock *puntst ) ;


El retorno de las mismas puede inicializar punteros del mismo tipo al
devuelto , distinto , por medio del uso del casting . Algunas funciones ,
tales como malloc() y calloc() definen su retorno como punteros a void :
void *malloc( int tamano ) ;
de esta forma al invocarlas , debemos indicar el tipo de puntero de
deseamos
p = (double *)malloc( 64 ) ;

Punteros y funciones
Introduccin
Absolutamente todos los datos en C pueden ser tratados como
punteros y por ello este lenguaje proporciona una serie de importantes
herramientas para trabajar con ellos.
Punteros
Qu son los punteros ?
Como su nombre indica un puntero es algo que apunta, es decir,
nos indica dnde se encuentra una cierta cosa. Supongamos (como
otras tantas veces) que disponemos de un gran archivo en el que
almacenamos informes. Este fichero est dividido en
compartimientos, cada uno de los cuales contiene uno de nuestros
informes (esto sera equivalente a las variables con las que hemos
trabajado hasta ahora -informes-, la cuales contienen informacin, y el
archivo representa la memoria de nuestro ordenador, obviamente las
variables se almacenan en la memoria). Sin embargo otros
compartimientos no contienen informes, sino que lo que contienen es
una nota que nos dice dnde est ese informe.
Supongamos que como mximo trabajamos con tres informes a la
vez, digamos que no nos gusta leer demasiado, y reservamos, por
tanto, tres compartimientos en los indicamos en que compartimiento
se encuentran esos tres informes. Estos tres compartimientos seran
nuestros punteros y como ocupan un compartimiento en el archivo
(nuestra memoria) son realmente variables, pero variables muy
especiales. Estas variables punteros ocupan siempre un tamao fijo,
simplemente contienen el nmero de compartimiento en el que se
encuentra la informacin. No contienen la informacin en s.

Si en nuestro archivo pudisemos almacenar un mximo de


20.000 hojas, esta sera la capacidad de nuestra memoria (unos 19
Kilobytes). Estas hojas de nuestros informes las agruparamos de
distintas formas. Quiz un informe slo ocupe 5 pginas mientras que
otro puede ocupar 100. Podemos ver esto como los distintos tipos de
datos del C, es lgico pensar que necesitamos ms espacio para
almacenar un nmero real que uno entero o que una matriz de 20x20
elemento. Estos son nuestros informes en nuestro archivo. Sin embargo
los punteros siempre ocupan lo mismo, en nuestro ejemplo nos
llegara con una pgina para poder escribir el nmero del
compartimiento en el que se encuentra el inicio del informe.
As en nuestro supuesto de que slo trabajemos con tres
informes a la vez, dispondramos de tres compartimientos en los que
indicaramos dnde se encuentran esos informes que buscamos y de
esta forma cuando terminemos con ellos y deseemos trabajar con otros
slo tendremos que cambiar el contenido de esos tres compartimientos
diciendo donde se encuentran los nuevos informes. De esta forma no
es necesario reservar unos compartimientos para trabajar y cada vez
que cambiemos de trabajo llevar los informes viejos a su
compartimiento anterior y traer los nuevos informes a estos
compartimientos.
Esto es lo que en programacin se conoce como referencia
indirecta o indirecin. Accedemos a la informacin a travs de un
puntero que nos dice dnde se encuentra sta. Y a grandes rasgos
esto son los punteros, referencias indirectas a datos en la memoria del
ordenador.
Los punteros en C son muy importantes puesto que su
utilizacin es bsica para la realizacin de numerosas operaciones.
Entre ellas: paso de parmetros que deseamos sean modificados,
tratamiento de estructuras dinmicas de datos (esto es, variables que
no se declaran en el programa y se crean durante la ejecucin del
programa), cadenas de caracteres ...
Operadores que actan sobre punteros.
El lenguaje C proporciona dos operadores relacionados
directamente con los punteros. El primero de ellos es el operador &. Ya
hemos visto este operador antes en las llamadas a la funcin scanf,
posteriormente explicaremos por que la funcin scanf necesita ser
llamada con el operador &.

El operador &, es un operador unario, es decir, acta sobre un slo


operando. Este operando tiene que ser obligatoriamente una estructura
direccionable, es decir, que se encuentre en la memoria del ordenador.
Estas estructuras son fundamentalmente las variables y las funciones,
de las que hablaremos posteriormente. Decimos que
slo se puede aplicar sobre estructuras direccionables porque su
funcin es devolver la posicin de memoria en la que se encuentra
dicha estructura. En nuestro ejemplo nos indicara cual sera el
compartimiento en el que se encuentra el informe que le indiquemos.
El segundo operador es el *. Tambin se trata de un operador
unario como el anterior y su funcin en este caso es la de permitir el
acceso al contenido de la posicin indicada por un puntero. En nuestro
ejemplo el operador * nos permitira leer o escribir el
informe al que apunta uno de nuestros compartimientos punteros.
Adems el carcter * se utiliza para declarar punteros los cuales como
ya dijimos tienen que ser declarados (tienen su propio
compartimiento en el archivo).
Por supuesto el operador * debe ser aplicado sobre un puntero,
mientras que el operador & sobre una estructura direccionable
(variable o funcin). Veamos un ejemplo de su utilizacin:
main ()
{
int x,y;
int *px;

/* Variables de tipo entero */


/* Puntero a una variable de tipo entero */

/* Leemos la direccin -compartimiento- de la variable


-informe- x mediante & y lo almacenamos en la variable puntero
px */
px = &x;
/* px contiene la direccin en la que se encuentra x */
/* Utilizando el operador *, podemos acceder a su
informacin. *px representa ahora el valor de la variable x */
*px = 10;
/* Ahora x contiene el valor 10 */
y = 15;
/* Si ahora hacemos que nuestro puntero apunte a la
variable y utilizando de nuevo el operador & */
px = &y;
/* El valor que ahora toma *px ser el valor de y puesto
que es el compartimiento al que ahora estamos apuntando */
*px = 125; /* Ahora y contiene el valor 125 */
x = *px /* Ahora x contiene tambin 125 */
}

Como hemos visto en este ejemplo es exactamente igual


acceder a una variable que utilizar un puntero que apunte a ella
(hacemos que apunte a ella mediante el operador &) junto con el
operador *.
Pero el lenguaje C an ofrece otra herramienta ms para
trabajar con punteros. Es lo que se suele llamar aritmtica de
punteros. Este tema lo trataremos en profundidad en el siguiente
apartado.

Punteros y matrices
Ya hemos hablado de las matrices en el tema anterior. Se trataba
de un conjunto de un nmero de terminado de variables de un mismo
tipo que se referenciaban con un nombre comn seguido de su
posicin entre corchetes con relacin al primer elemento. Todas las
entradas de una matriz estn consecutivas en memoria, por eso es muy
sencillo acceder al elemento que queramos en cada momento
simplemente indicando su posicin. Slo se le suma a la posicin
inicial ese ndice que indicamos. Es un ejemplo que casa
perfectamente con nuestro ejemplo de los informes, cada informe
podra ser considerado como una matriz de tantos elementos como
pginas tenga el informe y en los que cada uno de ellos es un tipo de
datos llamado pgina.
Las matrices son realmente punteros al inicio de una zona
consecutiva de los elementos indicados en su declaracin, por lo cual
podemos acceder a la matriz utilizando los corchetes como ya vimos o
utilizando el operador *.
elemento[i] <=> *(elemento +i)
Como ya se ha comentado todos los punteros ocupan lo mismo en
memoria, el espacio suficiente para contener una direccin, sin
embargo cuando se declaran es necesario indicar cul es el tipo de
datos al que van a apuntar (entero, real, alguna estructura definida por
el usuario). En nuestro ejemplo tendramos un tipo de puntero
por cada tipo de informe distinto, un puntero para informes de una
pgina, otro puntero para informes de 2 pginas y as sucesivamente.
En principio esto es irrelevante por que una direccin de memoria es una
direccin de memoria, independientemente de lo que contenga con lo
cual no sera necesario declarar ningn tipo, pero esta informacin
es necesaria para implementar la aritmtica de punteros que
ejemplificaremos a continuacin.

Supongamos que hemos definido un tipo de datos en nuestro


programa que fuese pgina, si cada pgina puede contener 80
caracteres de ancho por 25 de alto, podra ser algo como sto:
typedef char pgina[80][25];
Y supongamos tambin que slo tenemos tres tipos de
informes, de 1 pgina, de 5 pginas y de 25 pginas:
typedef pgina informe1;
typedef pgina informe2[5];
typedef pgina informe3[25];
Y en nuestro programa principal hemos declarado las
siguientes variables:
main()
{
pgina
informe1
informe2
informe3

*punt_pgina;
i1[10],*punt1;
i3[5],*punt2;
i4[15],*punt3;

....
Por tanto disponemos de un puntero a pginas y tres
punteros, uno para cada tipo de informe y tres matrices de distintos
tipos de informes que nos permiten almacenar en nuestro archivo un
mximo de 30 informes (10 de 1 pgina, 5 de 5 pginas y 15 de 25
pginas).
Supongamos que en el programa principal se llenan esas
matrices con datos (por teclado o leyendo de un fichero, por
ejemplo) y realizamos las siguientes operaciones:
punt_pgina = (pgina *) &i4[0];
punt3
= (informe3 *)&i4[0];
Los cast (que comentamos en el tema 1) convierten las
direcciones al tipo apropiado, las direcciones que contendrn
punt_pgina y punt3 sern exactamente iguales, apuntarn al
principio del primer informe de tipo3. Sin embargo punt_pgina es un
puntero de tipo pgina y punt3 es un puntero de tipo informe3, qu
significa sto?. Si ejecutsemos una instruccin como sta:

punt_pgina = punt_pgina + 5;
punt_pgina pasara a apuntar a la quinta pgina del primer
informe de tipo 3 (i4[0]), puesto que punt_pgina es un puntero de
pginas. Mientras que si la operacin fuese:
punt3 = punt3 + 5;
punt3 pasara a apuntar a el quinto informe de tipo 3 (i4[5]),
puesto que punt3 es un puntero a informes de tipo tres. Si ahora
realizsemos la operacin:
punt_pgina = (pgina *)punt3;
Ahora punt pgina apuntara a la primera pgina del quinto
informe de tipo 3. En esto consiste la aritmtica de punteros, cuando
se realiza una operacin aritmtica sobre un puntero las unidades de
sta son el tipo que se le ha asociado a dicho puntero.
Si el puntero es de tipo pgina operamos con pginas, si es de tipo
informes operamos con informes. Es evidente que un informe de tipo 3 y
una pgina tienen distintos tamaos (un informe de tipo 3 son 25
pginas por definicin).
Como hemos visto las matrices se pueden considerar como
punteros y las operaciones con esos punteros depende del tipo
asociado al puntero, adems es muy recomendable utilizar el cast
cuando se realizan conversiones de un tipo de puntero a otro.
Punteros y cadenas de caracteres
Como su propio nombre indica una cadena de caracteres es
precisamente eso un conjunto consecutivo de caracteres. Como ya
habamos comentado los caracteres se codifican utilizando el cdigo
ASCII que asigna un nmero desde 0 hasta 255 a cada uno de los
smbolos representables en nuestro ordenador. Las cadenas de
caracteres utilizan el valor 0 ('\0') para indicar su final. A este tipo de
codificacin se le ha llamado alguna vez ASCIIZ (la Z es de zero).
Las cadenas de caracteres se representan entre comillas dobles
(") y los caracteres simples, como ya habamos indicado con comillas
simples ('). Puesto que son un conjunto consecutivo de caracteres la
forma de definirlas es como una matriz de caracteres.
char identificador[tamao_de_la_cadena];

Y por ser en esencia una matriz todo lo comentado


anteriormente para matrices y punteros puede ser aplicado a ellas.
As la siguiente definicin constituye tambin una cadena de
caracteres:
char

*identificador;

La diferencia entre ambas declaraciones es que la primera


reserva una zona de memoria de tamao_de_la_cadena para almacenar
el mensaje que deseemos mientras que la segunda slo genera un
puntero.
La primer por tratarse de una matriz siempre tiene un puntero
asociado al inicio del bloque del tamao especificado. Podemos
tratar a las cadenas como punteros a caracteres (char *) pero
tenemos que recordar siempre que un puntero no contiene informacin
slo nos indica dnde se encuentra sta, por tanto con la segunda
definicin no podramos hacer gran cosa puesto que no tenemos
memoria reservada para ninguna informacin. Veamos un ejemplo para
comprender mejor la diferencia entra ambas declaraciones.
Utilizaremos dos funciones especiales de stdio.h para trabajar con
cadenas. Estas son puts y gets que definiramos como un printf y un
scanf exclusivo para cadenas.
#include <stdio.h>
main()
{
char
cadena1[10];
char
cadena2[10];
char
*cadena;
gets(cadena1); /* Leemos un texto por teclado y lo almacenamos
en cadena 1 */
gets(cadena2); /* Idem cadena2 */
puts (cadena1); /* Lo mostramos en pantalla */
puts (cadena2);
cadena = cadena1; /* cadena que slo es un puntero ahora apunta
a cadena1 en donde tenemos 10 caracteres reservados por la definicin
*/
puts (cadena); /* Mostrara en pantalla el mensaje
contenido en cadena1 */
cadena = cadena2; /* Ahora cadena apunta a la segunda

matriz de caracteres */
gets(cadena); /* Cuando llenos sobre cadena ahora
estamos leyendo sobre cadena2, debido al efecto de la instruccin
anterior */
puts(cadena2); /* SI imprimimos ahora cadena2 la pantalla
nos mostrar la cadena que acabamos de leer por teclado */
}
En el programa vemos como utilizamos cadena que solamente es
un puntero para apuntar a distintas zonas de memoria y utilizar
cadena1 o cadena2 como destino de nuestras operaciones. Como
podemos ver cuando cambiamos el valor de cadena a cadena1 o
cadena2 no utilizamos el operador de direccin &, puesto que como
ya hemos dicho una matriz es en s un puntero (si slo indicamos su
nombre) y por tanto una matriz o cadena de caracteres sigue siendo un
puntero, con lo cual los dos miembros de la igualdad son del mismo tipo
y por tanto no hay ningn problema.

Funciones
Introduccin
Hasta el momento hemos utilizado ya numerosas funciones,
como printf o scanf, las cuales forman parte de la librera estndar de
entrada/salida (stdio.h). Sin embargo el lenguaje C nos permite definir
nuestras propias funciones, es decir, podemos aadir al
lenguaje tantos comandos como deseemos.
Las funciones son bsicas en el desarrollo de un programa cuyo
tamao sea considerable, puesto que en este tipo de programas es
comn que se repitan fragmentos de cdigo, los cuales se pueden
incluir en una funcin con el consiguiente ahorro de memoria. Por otra
parte el uso de funciones divide un programa de gran tamao en
subprogramas ms pequeos (las funciones), facilitando su
comprensin, as como la correccin de errores.
Cuando llamamos a una funcin desde nuestra funcin
principal main() o desde otra funcin lo que estamos haciendo
realmente es un salto o bifurcacin al cdigo que le hayamos
asignado, en cierto modo es una forma de modificar el flujo de

control del programa como lo hacamos con los comandos while y for.
Definicin de funciones
Ya hemos visto cual es la estructura general de una funcin puesto
que nuestro programa principal, main() no es otra cosa que una
funcin. Veamos cual es el esquema genrico:
tipo_a_devolver identificador (tipo1 parmetro1, tipo2 ...)
{
tipo1 Variable_Local1;
tipo2 Variable_Local2;
...
Cdigo de la funcin
return valor del tipo valor a devolver;
}
Lo primero con lo que nos encontramos es la cabecera de la
funcin. Esta cabecera est formada por una serie de
declaraciones. En primer lugar el tipo_a_devolver.
Todas las funciones tienen la posibilidad de devolver un valor,
aunque pueden no hacerlo. Si definimos una funcin que nos calcula el
coseno de un cierto ngulo nos interesara que nuestra funcin
devolviese ese valor. Si por el contrario nuestra funcin
realiza el proceso de borrar la pantalla no existira ningn valor que nos
interesase conocer sobre esa funcin. Si no se especifica ningn
parmetro el compilador supondr que nuestra funcin devuelve un
valor entero (int).
A continuacin nos encontramos con el identificador de la funcin,
es decir, el nombre con el que la vamos a referenciar en nuestro
programas, seguido de una lista de parmetros entre parntesis y
separados por comas sobre los que actuar el cdigo
que escribamos para esa funcin. En el caso de la funcin coseno a la
que antes aludamos, el parmetro sera el ngulo calculamos el coseno
de un cierto ngulo que en cada llamada a la funcin probablemente
sea distinto. Vase la importancia de los parmetros, si no
pudisemos definir un parmetro para nuestra funcin coseno,
tendramos que definir una funcin para cada ngulo, en la que
obviamente no indicaramos ningn parmetro.
A continuacin nos encontramos el cuerpo de la funcin. En primer
lugar declaramos las variables locales de esa funcin.

Estas variables solamente podrn ser accedidas dentro de la


funcin, esto es, entre las llaves ({}). Los nombres de las variables
locales pueden ser los mismos en distintas funciones puesto que slo
son accesibles dentro de ellas. As si estamos acostumbrados a utilizar
una variable entera llamada i como contador en nuestro bucles,
podemos definir en distintas funciones esta variable y utilizarla dentro
de cada funcin sin que haya interferencias entre las distintas
funciones.
Con respecto al cdigo de la funcin, pues simplemente se trata
de un programa como todos los que hemos estado haciendo hasta
ahora.
La instruccin return del final puede omitirse si la funcin no
devuelve ningn valor, su cometido es simplemente indicar que valor
tomara esa funcin con los parmetros que le hemos pasado. En otros
lenguajes las funciones que no devuelven
valores se conocen como procedimientos.
Veamos un ejemplo de definicin de una funcin.
int
{
int

busca_elemento (int *vector,int valor,int longitud)


i;

for (i=0;i<longitud;i++)
if (vector[i] == valor) break;
return i;
}
Esta funcin busca un valor en un vector de nmeros enteros y
devuelve el ndice dentro de la matriz de la entrada de sta que lo
contiene. Puesto que devuelve el ndice de la matriz supondremos en
principio un valor de retorno entero para ese ndice. Los parmetros
que debe conocer la funcin son: la matriz en la que buscar, el valor
que debemos buscar y la longitud de la matriz. Podramos haber
realizado una funcin a medida para que utilizase una matriz de un
nmero determinado de elementos (int
vector[100], por ejemplo) y ahorrar el parmetro longitud, sin
embargo con la definicin que hemos hecho nuestra funcin
funcionar con matrices de cualquier longitud de enteros.
Hemos declarado adems una variable local que es necesaria para
la realizacin del bucle actuando como contador y conteniendo adems

el ndice dentro de la matriz que buscamos. Si la entrada i de nuestro


vector corresponde con valor, salimos del bucle y la
variable i contiene ese valor de la entrada, el cual es devuelto por la
funcin mediante la instruccin return. Ahora veremos cmo
utilizaramos esta funcin desde un programa:
main
{
int
int
int

()
matriz1[20];
matriz2[30];
indice,dato;

/* Aqu realizaramos alguna operacin sobre las


matrices como por ejemplo inicializarlas */
indice = busca_elemento (matriz1,10,20);
....
dato = 15;
indice = busca_elemento (matriz2,dato,30);
.....
}
Como vemos en las llamadas a nuestra funcin podemos
utilizar tanto variables o constantes como parmetros.
Ms sobre funciones
Cuando el valor que retornan las funciones no es entero, es
necesario que el compilador sepa de antemano su tipo por lo cual es
necesario aadir al comienzo del programa lo que se llaman prototipos.
Los prototipos simplemente son una predeclaracin de la funcin, solo
indican el tipo que devuelve, su nombre y los
tipos de los parmetros, no es necesario indicar un identificador para
los parmetros. Un prototipo para la funcin anterior sera:
int busca_elemento (int *, int, int);
Los fichero .h que se incluyen con la directiva del procesador
#include, contienen entre otras cosas los prototipos de las funciones a
las que nos dan acceso.
Para finalizar con las funciones vamos a explicar como pasar
parmetros que deseamos que la funcin modifique. Cuando pasamos

parmetros a una funcin sta realiza una copia de los valores de


stos en una zona de memoria propia, con lo cual la
funcin trabaja con estas copias de los valores y no hay peligro de que
se modifique la variable original con la que llamamos a la funcin,
forzando de esta forma a utilizar el valor retornado por la funcin como
parmetro. Sin embargo es posible que nos interese
que nuestra funcin nos devuelva ms de una valor o que uno de los
parmetros con los que lo llamamos se modifique en funcin de las
operaciones realizadas por la funcin. En este caso tenemos que pasar
los parmetros como punteros.
Cuando pasamos los valores como punteros la funcin realiza
una copia de los valores de los parmetros de las funciones en su
zona propia de memoria, pero en este caso el valor que pasamos no es
un valor en s, sino que es una direccin de
memoria en la que se encuentra ese valor que deseamos se
modifique, es decir, creamos un puntero que apunta a la posicin que
deseamos modificar, con lo cual tenemos acceso a esos valores.
Veamos un ejemplo tpico de parmetros que deben modificarse, este es
la funcin swap(a,b) cuya misin es intercambiar los valores de los dos
parmetros, es decir, el parmetro a toma el valor del parmetro b y
viceversa. La primera codificacin que se nos ocurre sera sta:
swap (int a,int b)
{
int
t;
t = a;
a = b;
b = t;
}
Y nuestro programa principal podra ser algo como sto:
main ()
{
int
c,d;
c = 5;
d = 7;
swap (c,d);
}
Veamos que pasa en la memoria de nuestro ordenador.

-Funcin main()
-Espacio para la variable c (Posicin de memoria x)
-Espacio para la variable d (Posicin de memoria y)
-Inicializacin de las variables
-swap(c,d)
-Fin de main()
-Funcin swap
-Cdigo de la funcin swap
-Espacio privado para almacenar los parmetros (Posicin
de memoria z)
En este ltimo compartimiento es dnde almacenamos los
valores de nuestros parmetros que sern respectivamente 5 y 7.
Despus de la ejecucin de swap en esta zona de memoria los
valores estn intercambiados, nuestro parmetro a que se
corresponde con la variable c en la llamada a swap contendr el valor
7 y el parmetro b correspondiente a d en la funcin main contendr el
valor 5. Esto es lo que se encuentra almacenado en la zona privada de
memoria de la funcin. Con este esquema cuando la funcin swap
termina su ejecucin y se devuelve el control al programa principal
main, los valores de c y d no han cambiado, puesto que los
compartimientos o posiciones de memoria x e y no han sido tocados
por la funcin swap, la cual slo ha actuado sobre el compartimiento z.
Si declaramos ahora nuestra funcin swap como sigue:
swap (int *p1,int *p2)
{
int
t;
t = *p1; /*Metemos en t el contenido de p1 */
*p1 = *p2; /* Contenido de p1 = contenido de p2 */
*p2 = t;
}
Tendremos el mismo esquema de nuestra memoria que antes
pero en lugar de almacenar en la zona privada de la funcin swap para
los parmetros los valores 5 y 7 tenemos almacenados en ella
los compartimientos en los que se encuentran, sto es, hemos
almacenado las posiciones x e y en lugar de 5 y 7. De esta forma
accedemos mediante un puntero a las variables c y d del programa
principal que se encuentran en las posiciones x e y modificndolas
directamente as que al regresar al programa principal sus valores
se encuentran ahora intercambiados.

En resumen, cuando deseemos que una funcin modifique el valor


de uno de los parmetros con los que es llamada debemos pasar un
puntero a esa variable en lugar del valor de esa variable. Es
evidente que si implementamos nuestra funcin de esta
forma, los parmetros jams podrn ser constantes, puesto que
difcilmente podramos modificar el valor de una constante.

Вам также может понравиться