Está en la página 1de 12

FUNCIONES - PASO DE PARMETROS

Paso de parmetros por valor. Paso de parmetros por referencia. Un caso especial: paso de listas como parmetros.

Parmetros reales.- Son las expresiones que aparecen en la llamada a una funcin. Por ejemplo, dada la sentencia: printf("Hola, Mundo\n"); la cadena "Hola, Mundo\n" es un parmetro real. Parmetros formales.- Son variables locales que se declaran en el encabezado de la funcin. os parmetros formales reciben el valor de los parmetros reales empleados en la llamada a la funcin. Paso de parmetros por valor. !"u# sucede internamente cuando se produce una llamada a una funcin$ %l proceso consta de varias fases sucesivas: &. %valuacin de las expresiones utilizadas como parmetros reales. '. (ctivacin de la funcin. ( su vez, esta fase posee otras: a. )eserva de espacio para los valores proporcionados por la funcin, si los *a+. b. (lmacenamiento de la direccin de retorno. c. )eserva de espacio para parmetros formales. d. )eserva de espacio para las dems variables locales, si las *ubiere. e. ,opia de los valores de los parmetros reales -+a evaluados al principio. en el espacio reservado para parmetros formales.

/. %jecucin. Se ejecutan las distintas sentencias de que consta el cuerpo de la funcin, *aciendo uso de la informacin aportada por los parmetros reales + almacenada previamente en los parmetros formales. 0. )etorno. 1ambi#n esta fase posee otras:
a.

(lmacenamiento del resultado de evaluar la expresin que acompa2a a return en el espacio reservado en '-a..

b. iberacin del espacio reservado para los parmetros formales + otras variables locales, si las *a+ c. Salto a la direccin de retorno, almacenada en '-b.. %sta activacin de la funcin *a concluido. 3bs#rvese que posiblemente *a+an quedado en la pila los valores para los cuales se reserv espacio en '-a.. %ste proceso, relativamente complejo, se realiza con notable velocidad en el procesador, que cuenta con instrucciones especializadas para muc*as de las fases que se *an mencionado. Pero ciertamente la fase de activacin + retorno supone un tiempo 4muerto4, en el sentido de que slo se efect5an clculos en la fase de ejecucin propiamente dic*a. %s bueno, entonces reducir el n5mero de llamadas a funcin cuando el tiempo necesario para las fases &, ' + 0 es comparable con el tiempo dedicado a la fase /. os compiladores, consciente de esto, admiten como opcin la creacin de funciones inline. 6eamos un ejemplo de llamada a una funcin en el cual se pueden ver todas las fases, aunque solo sea a trav#s de sus efectos. %videntemente, la activacin real de una funcin slo puede se7uirse 4en directo4 mediante un depurador que nos permita se7uir la ejecucin desde el nivel del len7uaje ensamblador , ejecutando una tras otra las instrucciones del len7uaje mquina. %sta tarea sobrepasa los l8mites de este curso, pero puede realizarse con relativa facilidad desde un 9:%. 6eamos el pro7rama: #include<stdio.h>

void f(int, float); int main(int argc, char ! int entero; float real; entero " ##; real " $$.$; printf("%ntes de llamar a f, entero vale &d ' real vale &(.#f\n", entero, real); f(entero, real); printf(")espu*s de volver de f, entero vale &d ' real vale &(.#f\n", entero, real); return +; , void f(int p, float -) ! printf("%l entrar en f, p (" entero) vale &d ' - (" real) vale &(.#f\n", p, -); p " ....; - " /#$01.(.; printf("%l salir de f, p vale &d ' - vale &(.#f\n", p, -); return; , 2 %ntes de llamar a f, entero vale ## ' real vale $$.$+ %l entrar en f, p (" entero) vale ## ' - (" real) vale $$.$+ %l salir de f, p vale .... ' - vale /#$01.(. )espu*s de volver de f, entero vale ## ' real vale $$.$+ 2 Comenterios.- os resultados del pro7rama confirman la argv)

descripcin efectuada ms arriba ms arriba. 3bs#rvese que los cambios efectuados en los parmetros formales p + - -que son variables locales de la funcin f(). no afectan -no pueden afectar- a los valores de los parmetros reales entero + real, que son variables locales de la funcin main(). Para ser exactos parmetro real entero tiene el valor '' + el parmetro real real tiene el valor //./. (l efectuar la llamada a la funcin, es como si se ejecutase el cdi7o si7uiente: p " entero; - " real; + por tanto p toma el valor '' + q toma el valor //./. ( continuacin, dentro de la funcin se ejecuta el se7mento de cdi7o: p " ....; - " /#$01.(.; + cambian los valores de p y q, se75n se comprueba mediante la sentencia printf() que contiene la funcin f(). Pero al volver a la funcin main() + escribir de nuevo -tras volver de f(), se75n se indica. los valores las variables locales de main(), se observa que no han cambiado los valores de entero y real. %sto si7nifica, desde un punto de vista 4macroscpico4, que en , el paso de parmetros est construido de tal manera que el paso de informacin es unidireccional: la informacin pasa de la funcin que *ace la llamada -la que aporta parmetros reales. a la funcin que recibe la llamada -la que tiene los parmetros formales. pero no en el sentido inverso. %sto se denomina paso de parmetros por valor. %n cierto sentido, esto es un problema, porque el objeto de los pro7ramas es procesar informacin, + es l7ico pensar que la funcin que *ace la llamada desea recibir la informacin procesada. ,iertamente se puede devolver informacin a trav#s del valor proporcionado por la funcin, pero esto es un cuello de botella + ser8a interesante disponer de al7una forma de alterar el valor de los parmetros reales a trav#s de los par;metros formales. %ste procedimiento existe, + consiste en pasar punteros como parmetros formales. 6#ase la seccin si7uiente.

Paso de parmetros por referen ia. %l paso de parmetros en , est construido de tal modo que los valores resultantes de evaluar los parmetros formales se copian en los parmetros formales. ,omo los parmetros formales son variables distintas de los parmetros reales, los cambios efectuados en los parmetros foramales no afectan para nada a los parmetros reales. %sto es cierto e insalvable, pero disponemos de un auxiliar sumamente interesante: los punteros. %n efecto, consid#rese el si7uiente fra7mento de cdi7o: int p; int - " 3p; - " $$; ,omo puede verse, *emos modificado el valor del entero p a trav#s de un puntero. ( todos los efectos, -equivale a p, esto es, se puede poner - en cualquier lu7ar en que aparezca p. %sto puede aplicarse al paso de parmetros: si en lugar de pasar el valor de un parmetro real se pasa la direccin del parmetro real en cuestin, entonces ser posible modificar el valor del parmetro real deshaciendo la indireccin (anteponiendo un asterisco al puntero) desde el interior de la funcin. ,onsid#rese el pro7rama si7uiente, que es una modificacin del empleado en la seccin anterior: #include<stdio.h> void f(int , float ); argv)

int main(int argc, char ! int entero; float real; entero " ##; real " $$.$;

printf("%ntes de llamar a f, entero vale &d ' real vale &(.#f\n", entero, real); f(3entero, 3real); printf(")espu*s de volver de f, entero vale &d ' real vale &(.#f\n", entero, real);

return +; , void f(int p, float -) ! printf("%l entrar en f, p (" entero) vale &d ' (" real) vale &(.#f\n", p, -); p " ....; - " /#$01.(.; printf("%l salir de f, p vale &d ' - vale &(.#f\n", p, -); return; , 2 4l resultado de e5ecutar este programa es el siguiente6 %ntes de llamar a f, entero $$.$+ %l entrar en f, p (" entero) vale $$.$+ %l salir de f, p vale .... ' )espu*s de volver de f, entero /#$01.(. 2 vale ## ' real vale vale ## ' - (" real)

vale /#$01.(. vale .... ' real vale

Comentarios.- %ste pro7rama tiene un comportamiento sutilmente distinto del anterior. (l *acer la llamada a la funcin, se eval5an los parmetros reales, que son 3entero + 3real, respectivamente. os valores de estos parmetros son las direcciones de entero + real, respectivamente. ue7o al llamar a esta funcin es como si se ejecutase el si7uiente fra7mento de cdi7o: p " 3entero; - " 3real;

de modo que p pasa a contener la direccin de entero + - pasa a contener la direccin de real. %ntonces p equivale por completo a entero + - equivale por completo a real, puesto que el operador asterisco antepuesto a un puntero des*ace la indireccin + proporciona la variable se2alada por el puntero al que se antepone. ,omo p equivale a entero, poner p " .... es exactamente lo mismo que ponerentero " ...., + anlo7amente poner - " /#$01.(. equivale a poner real " /#$01.(.. %n resumidas cuentas, al pasar como parmetros punteros en lugar de valores, se pueden modificar los valores sealados por los punteros (los parmetros reales). %sto se denomina paso por referen ia. Se ve entonces que la comunicacin entre funciones puede ser monodireccional o bidirecional, a nuestro arbitrio: Para efectuar una comunicacin monodireccional, se pasan variables estndar como parmetros reales Para efectuar una comunicacin bidireccional, se pasan punteros como parmetros reales

< desde lue7o, tanto las variables estndar como los punteros pasan por valor, esto es, las modificaciones efectuadas en los parmetros -variables estndar o punteros. dentro de la funcin no afectan a las variables estndar o punteros empleados como parmetros reales. o 5nico que puede resultar afectado son las variables sealadas por los punteros pasados como parmetros. Podr8a pensarse, entonces, que no se puede modificar el valor de un puntero cuando #ste pasa como parmetro, + as8 es. (*ora bien, en , existe el concepto de doble indireccin, o puntero de puntero. =ada impide utilizar un puntero de puntero como parmetro de una funcin, lue7o dentro de la funcin se dispone de la direccin del puntero, as8 que es posible modificar su valor. ,onsid#rese el pro7rama si7uiente: #include<stdio.h>

#define M%7 /+ void crear(int -); argv89)

int main(int argc, char !

int p; int i; crear(3p); if (p :" ;<==) ! for(i"+;i<M%7;i>>) p8i9 " i; for(i"+;i<M%7;i>>) printf("p8&d9 vale &d\n", i, p8i9); , else printf("\n;o ha' memoria suficiente\n"); return +; , void crear(int -) ! - " (int )malloc(M%7 si?eof(int)); , 2 p8/9 p8#9 p8$9 p809 p819 p8(9 p8.9 p8@9 p8A9 2 vale vale vale vale vale vale vale vale vale / # $ 0 1 ( . @ A

%n la llamada a la funcin crear(), el parmetro real es 3p> este valor se copia en el parmetro formal, -. Por tanto, en la llamada a la funcin es como si se ejecutase el cdi7o: - " 3p; que almacena en - la direccin de p. %ntonces, si se antepone un asterisco a -, se obtiene precisamentep. ue7o

podemos asi7nar a - el resultado de una llamada a malloc(), que reserva memoria para toda una lista. os punteros tienen la posibilidad de admitir un 8ndice, + eso es precisamente lo que se *ace en el pro7rama principal, una vez asi7nado a p un valor que es la direccin del bloque reservado por malloc(). %n resumen, *emos pasado p a crear() por referencia> esto nos *a permitido modificar el valor de pdesde dentro de crear(), + utilizar entonces el nuevo valor de p desde el pro7rama principal. Un aso espe ial! paso de listas omo parmetros. %l compilador de , trata las listas monodimensionales como si fuesen punteros del tipo base de la lista en cuestin. ( todos los efectos, una lista monodimensional se trata como un puntero cu+o valor es la direccin del primer elemento de la lista. :ic*o formalmente, si se tiene la declaracin: BipoCDase lista8M%79; entonces es como si lista fuera equivalente a 3lista8+9. %sto tiene consecuencias inmediatas cuando se pasa una lista como parmetro a una funcin: todas las listas en C pasan por referencia, porque su nombre equivale automticamente a la direccin de su primer elemento. ,onsid#rese el ejemplo si7uiente: #include<stdio.h> #define M%7 #+ void leer(char void leer#(char p); p); argv89)!

int main(int argc, char

char nomDre8M%79; printf("4scriDa un nomDre6 "); leer(nomDre); printf("4l nomDre -ue ha escrito es &s\n", nomDre); return +; , void leer(char p)

! fgets(p, M%7, stdin); fpurge(stdin); , void leer#(char p) ! si?eCt n; fgets(p, M%7, stdin); fgetln(stdin, 3n); if (n :" +) ! printf("=impie?a...\n\n"); fpurge(stdin); , , 2 4scriDa un nomDre6 Miguel de <namuno ' Eugo 4l nomDre -ue ha escrito es Miguel de <namuno ' 2 Comentarios.- %n este pro7rama se pasa una lista de char llamada nomDre a la funcin leer(). ,omo las listas equivalen a la direccin de su primer elemento, se admite el parmetro real nombre. (l efectuar la llamada a la funcin, es como si se ejecutase el cdi7o si7uiente: p " 3nomDre8+9; de modo que se car7a en p la direccin del primer elemento de nombre. %ntonces p se puede emplear, a su vez, como ar7umento de fgets() + de este modo leemos tantos caracteres como indica M%7. a lectura no tiene peli7ro. Por si acaso, *emos llamado a la funcin fpurge() para eliminar posibles restos del b5fer de teclado. a funcin leer#() emite un aviso si realmente *ab8a necesidad de 4limpieza4.

E"er i ios prop#estos

&.
#. $. 0. 1. (.

E"er i io $%$&r$'(struct Fegistro ! char n80+9; float f; int n8/+9; ,;

,onsid#rese la declaracin

Se pide construir una funcin que admita ar7umentos de tipo )e7istro, + que muestre sus campos en pantalla, con formato en columnado.
?. E"er i io $%$&r$)(-

,onsid#rese la declaracin

@. struct Fegistro ! A. char n80+9; /+. float f; //. int n8/+9; /#. ,;

Se pide construir una funcin que admita parmetros de este tipo + pida los datos de sus campos al usuario, para devolver la estructura, con sus datos +a cumplimentados, a la funcin que *a+a *ec*o la llamada. !,mo pasan las estructuras, por valor o por referencia$
&/.
/0. /1. /(. /.. /@.

E"er i io $%$&r$&(struct Fegistro ! char n80+9; float f; int n8/+9; ,;

,onsid#rese la declaracin

Se dispone de una lista de estructuras de este tipo, formada por @(A elementos. Se pide construir una funcin que admita la lista + rellene los campos de todas sus estructuras con unos valores iniciales preestablecidos.
&B.

Se dispone de una matriz -una tabla. de dimensiones @x=, formada por elementos de tipo double. Se pide construir una funcin que admita la matriz como ar7umento + determine qu# fila + qu# columna contiene ms veces el valor C.C.
E"er i io $%$&r$*(-

'C.

Se proporciona a un pro7rama una coleccin de valores de tipo float, escribi#ndolos en la l8nea de rdenes. Se pide construir una funcin que proporcione como resultado una estructura a trav#s de un puntero. a estructura tendr como campos una lista de float -los pasados a trav#s de la l8nea de rdenes. + un campo que indique el n5mero de elementos de la lista.
E"er i io $%$&r$+(-

21. E"er i io $%$&r$,(-

,onstruir una funcin que admita como ar7umento el puntero de una lista de punteros de estructuras anlo7as a la empleada en el %jercicio &. a funcin debe proporcionar un puntero de la estructura que conten7a el valor ms 7rande en el campo f. ,onstruir una funcin que admita como ar7umento una cadena de formato encolumnado + proporcione, mediante un puntero, el valor de cualquiera de sus campos de tipo float. ,onstruir otras funciones anlo7as para campos de tipo cadena + de tipo int. Si *a+ errores manifiestos, la funcin lo comunicar a trav#s de un puntero de int. onstruir una funcin que admita como ar7umento una cadena de formato delimitado + proporcione, mediante un puntero, el valor de cualquiera de sus campos de tipo douDle. ,onstruir otras funciones anlo7as para campos de tipo cadena + de tipo int. Si *a+ errores manifiestos, la funcin lo comunicar a trav#s de un puntero de int.

22. E"er i io $%$&r$-(-

23. E"er i io $%$&r$%(-