Parámetros y Argumentos en el Lenguaje de Programación C++
Parámetros y Argumentos en el Lenguaje de Programación C++
Parámetros y Argumentos en el Lenguaje de Programación C++
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Editorial <strong>de</strong> la Universidad<br />
Tecnológica Nacional<br />
Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Área <strong>de</strong> Programación<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> L<strong>en</strong>guaje <strong>de</strong><br />
Programación <strong>C++</strong><br />
Ing. Ubaldo José Bonaparte<br />
Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información<br />
Facultad Regional Tucumán<br />
Universidad Tecnológica Nacional<br />
U.T.N. - Arg<strong>en</strong>tina<br />
Editorial <strong>de</strong> la Universidad Tecnológica Nacional - edUTecNe<br />
http://www.edutecne.utn.edu.ar<br />
edutecne@utn.edu.ar
2- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Prologo:<br />
Consi<strong>de</strong>rando la necesidad <strong>de</strong> una comunicación fluida <strong>en</strong>tre los<br />
doc<strong>en</strong>tes, fundam<strong>en</strong>talm<strong>en</strong>te <strong>en</strong>tre profesores d<strong>el</strong> Area <strong>de</strong> Programación 1 ,<br />
<strong>de</strong> la carrera <strong>de</strong> Ing<strong>en</strong>iería <strong>en</strong> Sistemas <strong>de</strong> Información, como integrante 2<br />
<strong>de</strong> la cátedra <strong>de</strong> Paradigmas <strong>de</strong> Programación <strong>el</strong>eve <strong>el</strong> proyecto “Ciclos<br />
<strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación”. Dicho proyecto<br />
contempla la exposición <strong>de</strong> temas incluidos <strong>en</strong> la curricula o bi<strong>en</strong> <strong>de</strong><br />
actualidad, y <strong>el</strong> <strong>de</strong>bate <strong>en</strong>tre los pres<strong>en</strong>tes con <strong>el</strong> fin <strong>de</strong> mejorar nuestra<br />
didáctica, cont<strong>en</strong>idos teórico-prácticos y bibliografías.<br />
Parti<strong>en</strong>do <strong>de</strong> esta base, <strong>de</strong> gran importancia hacia un futuro<br />
perfeccionado <strong>de</strong> nuestros estudiantes, y <strong>de</strong>s<strong>de</strong> luego <strong>de</strong> nuestros<br />
doc<strong>en</strong>tes, creo indisp<strong>en</strong>sable que las palabras expresadas <strong>en</strong> los<br />
seminarios qued<strong>en</strong> docum<strong>en</strong>tadas a partir <strong>de</strong> escritos <strong>de</strong> este tipo.<br />
Detallando conceptos y ejemplificándolos <strong>de</strong> modo que toda persona<br />
r<strong>el</strong>acionada a esta casa <strong>de</strong> altos estudios, pueda consultar y <strong>en</strong>riquecer sus<br />
conocimi<strong>en</strong>tos.<br />
En estas líneas procuro introducir al lector a un tema muy<br />
específico d<strong>en</strong>tro <strong>de</strong> la programación utilizando <strong>el</strong> l<strong>en</strong>guaje <strong>C++</strong>.<br />
Simplem<strong>en</strong>te apunto a lectores con conocimi<strong>en</strong>tos básicos <strong>en</strong> dicho<br />
l<strong>en</strong>guaje y con ganas <strong>de</strong> aclarar o bi<strong>en</strong> perfeccionar sus programas<br />
haci<strong>en</strong>do un bu<strong>en</strong> uso <strong>de</strong> estas herrami<strong>en</strong>tas d<strong>en</strong>ominadas parámetros o<br />
argum<strong>en</strong>tos.<br />
1 Departam<strong>en</strong>to <strong>de</strong> Ing<strong>en</strong>iería <strong>en</strong> Sistemas <strong>de</strong> Información, Facultad Regional Tucumán<br />
2 Profesor Asociado Ordinario, Jefe <strong>de</strong> cátedra.
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 3<br />
Ing. Ubaldo José Bonaparte<br />
Indice<br />
1. Introducción 4<br />
2. Conceptos <strong>de</strong> Parámetros y <strong>Argum<strong>en</strong>tos</strong> 8<br />
3. Tipos <strong>de</strong> parámetros 8<br />
3.1. Parámetros por valor 9<br />
3.2. Parámetros por refer<strong>en</strong>cia 9<br />
3.3. Parámetros por refer<strong>en</strong>cia puntero 12<br />
3.4. Combinando tipos <strong>de</strong> parámetros 15<br />
4. La función main() y sus argum<strong>en</strong>tos 16<br />
5. Variedad <strong>de</strong> ejemplos usando parámetros 18<br />
5.1. Variable nativa <strong>en</strong>tera simple 18<br />
5.2. Variable <strong>de</strong> tipo estructura 19<br />
5.3. Variable <strong>de</strong> tipo estructura autorefer<strong>en</strong>ciada 20<br />
6. Variantes <strong>de</strong> parámetros y argum<strong>en</strong>tos 23<br />
6.1. <strong>Argum<strong>en</strong>tos</strong> por <strong>de</strong>fecto u omisión 23<br />
6.2. <strong>Argum<strong>en</strong>tos</strong> punteros a void 24<br />
6.3. <strong>Argum<strong>en</strong>tos</strong> no especificados o variables 25<br />
7. Conclusiones 35<br />
8. Bibliografía 35
4- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Introducción:<br />
Cuando com<strong>en</strong>zamos a vincularnos con <strong>el</strong> apr<strong>en</strong>dizaje d<strong>el</strong><br />
<strong>de</strong>sarrollo <strong>de</strong> programas o bi<strong>en</strong> con algún l<strong>en</strong>guaje <strong>de</strong> programación <strong>en</strong><br />
particular, incorporamos una serie <strong>de</strong> conceptos nuevos que no formaban<br />
parte <strong>de</strong> nuestros días cotidianos. Lógica, variables, constantes,<br />
estructuras <strong>de</strong> datos, archivos, subprogramas, funciones etc. etc.<br />
Ent<strong>en</strong><strong>de</strong>mos la secu<strong>en</strong>cialidad <strong>de</strong> la ejecución <strong>de</strong> nuestros comandos o<br />
s<strong>en</strong>t<strong>en</strong>cias <strong>de</strong> programas, captamos los conceptos <strong>de</strong> input y output,<br />
hacemos nuestros primeros programas, continuamos creándolos y quizá<br />
<strong>de</strong>spués <strong>de</strong> unos cincu<strong>en</strong>ta expresamos saber programar.<br />
Ahora bi<strong>en</strong>, siempre he p<strong>en</strong>sado que <strong>el</strong> arte <strong>de</strong> programar requiere<br />
<strong>de</strong> un alto porc<strong>en</strong>taje <strong>de</strong> conocimi<strong>en</strong>tos sobre las herrami<strong>en</strong>tas que nos<br />
brinda <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación con <strong>el</strong> que trabajamos. Eso por un<br />
lado. Por otro, nuestra creatividad <strong>de</strong>be estar motivada y sust<strong>en</strong>tada sobre<br />
una base muy sólida <strong>de</strong> <strong>de</strong>talles madurados sobre lo que t<strong>en</strong>emos que<br />
programar. Así también, siempre p<strong>en</strong>samos que nuestros programas<br />
<strong>de</strong>b<strong>en</strong> ser amigables con <strong>el</strong> usuario, sólidos, consist<strong>en</strong>tes y robustos.<br />
Cuantas veces consultamos con colegas o bibliografía, sobre<br />
<strong>de</strong>talles m<strong>en</strong>ores o muy importantes ya que no visualizamos como aplicar<br />
nuestras herrami<strong>en</strong>tas para un fin <strong>de</strong>terminado. Des<strong>de</strong> luego apr<strong>en</strong><strong>de</strong>mos<br />
constantem<strong>en</strong>te y lo mejor <strong>de</strong> todo, es que nuestros proveedores <strong>de</strong><br />
l<strong>en</strong>guajes <strong>de</strong> programación no <strong>de</strong>jan <strong>de</strong> brindarnos tecnología nueva que<br />
nos exija <strong>de</strong>dicación, estudio y mucha práctica.<br />
Este seminario ti<strong>en</strong>e la bondad <strong>de</strong> hacer un aporte sobre <strong>el</strong><br />
paradigma procedim<strong>en</strong>tal, como parte <strong>de</strong> la programación imperativa<br />
puntualm<strong>en</strong>te sobre parámetros y argum<strong>en</strong>tos <strong>en</strong> funciones <strong>de</strong>sarrolladas<br />
<strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>. Siempre procurando trabajar sobre<br />
la formación d<strong>el</strong> programador <strong>en</strong> cuanto al ord<strong>en</strong> y manejo, que <strong>de</strong>be<br />
t<strong>en</strong>er sobre las variables y sus ámbitos <strong>en</strong> un programa. Y tratando <strong>de</strong><br />
evitar los efectos colaterales que produce <strong>el</strong> per<strong>de</strong>r control sobre las<br />
mismas.<br />
Los parámetros y argum<strong>en</strong>tos forman parte es<strong>en</strong>cial para la<br />
comunicación <strong>en</strong>tre funciones o procedimi<strong>en</strong>tos <strong>de</strong> nuestros programas.
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 5<br />
Ing. Ubaldo José Bonaparte<br />
Ya que por paradigma, es prohibitivo <strong>el</strong> manejo <strong>de</strong> variables<br />
globales, que si podrían ser reconocidas <strong>de</strong>s<strong>de</strong> procedimi<strong>en</strong>tos y<br />
funciones, nuestro recurso <strong>de</strong> comunicación se acreci<strong>en</strong>ta a partir <strong>de</strong><br />
parámetros y argum<strong>en</strong>tos. O sea, <strong>el</strong> ámbito <strong>de</strong> nuestras variables <strong>de</strong>be ser<br />
la función don<strong>de</strong> fueron <strong>de</strong>claradas y si necesitamos dichas variables <strong>en</strong><br />
otras funciones, haremos uso <strong>de</strong> parámetros y argum<strong>en</strong>tos para disponer<br />
<strong>de</strong> <strong>el</strong>las a<strong>de</strong>cuadam<strong>en</strong>te.<br />
Entonces, a partir <strong>de</strong> parámetros y argum<strong>en</strong>tos vamos a respetar y<br />
ext<strong>en</strong><strong>de</strong>r <strong>el</strong> ámbito <strong>de</strong> variables locales?. Si, eso trataremos <strong>de</strong> lograr y<br />
nos olvidaremos <strong>de</strong> gran parte <strong>de</strong> los efectos colaterales que las variables<br />
pued<strong>en</strong> producir.<br />
Un ejemplo simple para analizar<br />
Cargar los valores <strong>de</strong> un vector <strong>de</strong> números <strong>en</strong>teros, mostrar sus<br />
valores y obt<strong>en</strong>er la suma <strong>de</strong> dichos valores, significaría <strong>de</strong>sarrollar <strong>el</strong><br />
sigui<strong>en</strong>te programa.<br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
int arreglo[5] = {0,0,0,0,0}; // variable global inicializada<br />
void carga(){<br />
int i;<br />
for (i = 0; i < 5; i++)<br />
cin >> arreglo[i];<br />
}<br />
void muestra(){<br />
for (int i = 0;i < 5;i++)<br />
printf("%d,",arreglo[i]);<br />
}<br />
int suma(){<br />
int i,valor;
6- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
valor = 0;<br />
for (i = 0;i < 5;i++)<br />
valor += arreglo[i];<br />
return(valor);<br />
}<br />
void main(){<br />
carga();<br />
muestra();<br />
printf("\nLa suma <strong>de</strong> los <strong>el</strong>em<strong>en</strong>tos es = %d\n",suma());<br />
}<br />
La variable arreglo, <strong>de</strong> tipo vector <strong>de</strong> <strong>en</strong>teros es global al<br />
programa. Significa que po<strong>de</strong>mos disponer <strong>de</strong> <strong>el</strong>la <strong>en</strong> cualquier función,<br />
para observar u obt<strong>en</strong>er sus datos o bi<strong>en</strong> para modificarlos. Las variables<br />
i <strong>de</strong> tipo <strong>en</strong>tero, que utilizamos para variar los subíndices, ti<strong>en</strong><strong>en</strong> sus<br />
ámbitos <strong>en</strong> cada función; y porque no, podría haber sido global. Qui<strong>en</strong><br />
expresaría que este programa esta mal escrito, que ti<strong>en</strong>e efectos<br />
colaterales?. Dada su magnitud, ext<strong>en</strong>sión, cantidad <strong>de</strong> líneas y<br />
simplicidad, este programa no estaría mal escrito. Pero si aportaría sobre<br />
los malos hábitos <strong>de</strong> un futuro programador.<br />
Mejoremos nuestro primer ejemplo.<br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
type<strong>de</strong>f int arreglo[]; // <strong>de</strong>claración <strong>de</strong> un tipo arreglo <strong>de</strong> <strong>en</strong>teros<br />
void carga(arreglo &a){<br />
for (int i = 0;i < 5;i++)<br />
cin>>a[i];<br />
}<br />
void muestra(arreglo b){<br />
for (int i = 0;i < 5;i++)<br />
printf("%d,",b[i]);<br />
}
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 7<br />
Ing. Ubaldo José Bonaparte<br />
int suma(arreglo c){<br />
int valor = 0;<br />
for (int i = 0;i < 5;i++)<br />
valor += c[i];<br />
return(valor);<br />
}<br />
void main(){<br />
arreglo vector = {0,0,0,0,0};<br />
carga(vector);<br />
muestra(vector);<br />
printf("\nLa suma <strong>de</strong> los <strong>el</strong>em<strong>en</strong>tos es = %d\n",suma(vector));<br />
}<br />
Este programa funciona casi como <strong>el</strong> ejemplo anterior, para <strong>el</strong><br />
usuario se diría que igual. Nosotros como programadores observamos<br />
que las cosas son muy distintas. Disponemos d<strong>el</strong> tipo arreglo, que nos<br />
permite <strong>de</strong>finir variables <strong>de</strong> tipo arreglos <strong>de</strong> números <strong>en</strong>teros y<br />
dim<strong>en</strong>sionarlos. Definimos la variable vector local a la función main() y<br />
si queremos utilizarla <strong>en</strong> otras funciones, al invocarlas la pasamos como<br />
parámetro. A<strong>de</strong>más observamos que las variables i, ti<strong>en</strong><strong>en</strong> como ámbito<br />
solo las estructuras don<strong>de</strong> las usamos.<br />
Estamos com<strong>en</strong>zando a t<strong>en</strong>er bu<strong>en</strong>os hábitos, no <strong>de</strong>clarando<br />
variables globales, ext<strong>en</strong>di<strong>en</strong>do ámbitos <strong>de</strong> variables locales a funciones<br />
pasándolas como parámetros y <strong>de</strong>clarando variables solo <strong>en</strong> ámbitos<br />
don<strong>de</strong> son necesarias.
8- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Conceptos <strong>de</strong> Parámetros y <strong>Argum<strong>en</strong>tos</strong><br />
Son <strong>el</strong> medio a partir d<strong>el</strong> cual po<strong>de</strong>mos expandir <strong>el</strong> ámbito <strong>de</strong><br />
variables locales <strong>de</strong> funciones, hacia otras funciones y a<strong>de</strong>más qui<strong>en</strong>es<br />
nos permit<strong>en</strong> establecer comunicaciones <strong>en</strong>tre funciones. Si nos vemos<br />
ante la necesidad <strong>de</strong> visualizar o modificar <strong>el</strong> valor <strong>de</strong> una variable local<br />
<strong>en</strong> otra función que llamaremos, <strong>de</strong>bemos invocar a dicha función<br />
haci<strong>en</strong>do refer<strong>en</strong>cia <strong>de</strong> su nombre, seguido <strong>de</strong> los parámetros o nombres<br />
<strong>de</strong> variables para las cuales, <strong>en</strong> teoría ampliaríamos su ámbito.<br />
void funcion_llamada(int x){ // función que recibe un argum<strong>en</strong>to<br />
:<br />
}<br />
void una_funcion(void){<br />
int a,b; // variables <strong>de</strong> ámbito local<br />
:<br />
:<br />
funcion_llamada(a); // llamada <strong>de</strong> la función con un parámetro<br />
:<br />
}<br />
La expresión funcion_llamada(a); se d<strong>en</strong>omina llamado a la función<br />
funcion_llamada con un parámetro a <strong>de</strong> tipo <strong>en</strong>tero. Y la expresión void<br />
funcion_llamada(int x) se d<strong>en</strong>omina cabecera <strong>de</strong> la función<br />
funcion_llamada con un argum<strong>en</strong>to, <strong>en</strong> este caso x, también <strong>de</strong> tipo<br />
<strong>en</strong>tero.<br />
Des<strong>de</strong> luego que, sobre la base <strong>de</strong> la comunicación <strong>en</strong>tre<br />
funciones y la teoría d<strong>el</strong> paradigma procedim<strong>en</strong>tal don<strong>de</strong> aplicamos la<br />
disgregación <strong>de</strong> procesos, nos po<strong>de</strong>mos <strong>en</strong>contrar con las sigui<strong>en</strong>tes<br />
variantes:<br />
1. Llamado <strong>de</strong> funciones sin pasar parámetros.<br />
2. Llamado <strong>de</strong> funciones pasando parámetros.<br />
esta claro que dichas funciones pued<strong>en</strong> o no <strong>de</strong>volvernos valores hacia <strong>el</strong><br />
orig<strong>en</strong> <strong>de</strong> su llamado.
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 9<br />
Ing. Ubaldo José Bonaparte<br />
Entonces, pasamos como parámetros nombres <strong>de</strong> variables al<br />
llamar una función, que <strong>de</strong>b<strong>en</strong> correspon<strong>de</strong>rse <strong>en</strong> su tipo al ser recibidos<br />
sobre los argum<strong>en</strong>tos <strong>de</strong> dicha función. Esto básicam<strong>en</strong>te es correcto,<br />
pero <strong>de</strong>bemos completar la i<strong>de</strong>a <strong>de</strong>scribi<strong>en</strong>do con claridad los tipos <strong>de</strong><br />
parámetros que nos permite manejar <strong>el</strong> l<strong>en</strong>guaje <strong>C++</strong>.<br />
Tipos <strong>de</strong> parámetros<br />
Los tipos <strong>de</strong> parámetros a utilizar van a <strong>de</strong>p<strong>en</strong><strong>de</strong>r siempre <strong>de</strong> la<br />
necesidad que se le pres<strong>en</strong>te al programador. De todos modos hay dos<br />
necesida<strong>de</strong>s básicas que g<strong>en</strong>eralm<strong>en</strong>te están vig<strong>en</strong>tes:<br />
1. Po<strong>de</strong>r obt<strong>en</strong>er <strong>el</strong> cont<strong>en</strong>ido <strong>de</strong> una variable.<br />
2. Po<strong>de</strong>r modificar <strong>el</strong> cont<strong>en</strong>ido <strong>de</strong> una variable.<br />
Parámetros por valor<br />
Cuando surge la necesidad <strong>de</strong> obt<strong>en</strong>er <strong>el</strong> valor o cont<strong>en</strong>ido <strong>de</strong> una<br />
variable original o local a una función, <strong>en</strong> otra función, se utiliza<br />
parámetros por valor. En este caso se produce una copia <strong>de</strong> la variable<br />
original hacia <strong>el</strong> argum<strong>en</strong>to formal <strong>de</strong> la función receptora. Dicha<br />
variable t<strong>en</strong>drá como ámbito la función receptora y al culminar esta<br />
liberará <strong>el</strong> espacio <strong>de</strong> memoria que ocupa.<br />
void imprime_cantidad(int can){<br />
printf(“%d\n”,can);<br />
}<br />
void alguna_funcion(void){<br />
int cantidad;<br />
:<br />
imprime_cantidad(cantidad);<br />
:<br />
}<br />
El valor <strong>de</strong> una variable original pue<strong>de</strong> pasar <strong>de</strong> una función a<br />
otra y a su vez a otras funciones, sin inconv<strong>en</strong>i<strong>en</strong>tes. De pronto <strong>en</strong>
10- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
nuestro <strong>de</strong>sarrollo, nos po<strong>de</strong>mos <strong>en</strong>contrar con una hoja <strong>de</strong> ruta <strong>de</strong><br />
valores <strong>de</strong> variables que pasan por funciones.<br />
Si usamos parámetros por valor, nunca podremos modificar los<br />
valores <strong>de</strong> las variables originales ya que se produc<strong>en</strong> copias <strong>de</strong> las<br />
mismas hacia las variables <strong>de</strong> la función llamada y su ámbito es local.<br />
Al utilizar parámetros por valor, éstos pued<strong>en</strong> ser constantes<br />
como por ejemplo:<br />
#inclu<strong>de</strong> <br />
void imprime_datos(char nombre[], int edad){<br />
printf("Nombre :%s , edad: %d\n",nombre, edad);<br />
}<br />
void main(void){<br />
char alias[35] = {"Pepe"};<br />
imprime_datos(alias,23);<br />
}<br />
Parámetros por refer<strong>en</strong>cia<br />
La refer<strong>en</strong>cia indica trabajar sobre la dirección <strong>de</strong> memoria que<br />
ocupa <strong>el</strong> parámetro o variable original.<br />
void ingresar_cantidad(int &can){<br />
cin>>can;<br />
}<br />
void alguna_funcion(void){<br />
int cantidad;<br />
:<br />
ingresar_cantidad(cantidad);<br />
:<br />
}
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 11<br />
Ing. Ubaldo José Bonaparte<br />
Como se observa <strong>en</strong> este ejemplo, <strong>el</strong> argum<strong>en</strong>to <strong>de</strong> la función<br />
receptora, pres<strong>en</strong>ta <strong>el</strong> operador unario & precedi<strong>en</strong>do al nombre <strong>de</strong> la<br />
variable. Esto indica que se tome la dirección d<strong>el</strong> parámetro hacia <strong>el</strong><br />
argum<strong>en</strong>to, produci<strong>en</strong>do un espejo o alias <strong>de</strong> la variable original<br />
cantidad. Lo cual significará, que toda alteración producida sobre <strong>el</strong><br />
argum<strong>en</strong>to can, afectará a la variable original o parámetro cantidad.<br />
Siempre que surja la necesidad <strong>de</strong> afectar a las variables<br />
originales <strong>de</strong>bemos usar parámetros por refer<strong>en</strong>cia. Algunos casos serían:<br />
cargar un dato o recalcular un dato.<br />
Ya que las funciones <strong>de</strong>vu<strong>el</strong>v<strong>en</strong> solo un valor, es habitual usar<br />
varios parámetros por refer<strong>en</strong>cia cuando necesitamos que una función<br />
provoque varios resultados y no solo uno.<br />
Si al argum<strong>en</strong>to por refer<strong>en</strong>cia lo prece<strong>de</strong>mos <strong>de</strong> la palabra const,<br />
dicha variable no podrá ser alterada <strong>en</strong> <strong>el</strong> ámbito <strong>de</strong> la función receptora,<br />
por lo tanto nunca afectará a la variable original.<br />
#inclu<strong>de</strong> <br />
void icrem<strong>en</strong>ta_sin_exito(int b)<br />
{ b++;} // no afecta a la variable original a<br />
void increm<strong>en</strong>ta_con_exito(const int &b)<br />
{ b++;} // Error <strong>de</strong> compilación<br />
void main(void){<br />
int a = 4;<br />
cout
12- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Parámetros por refer<strong>en</strong>cia puntero<br />
Kernighan y Ritchie 3 <strong>el</strong> su capítulo apuntadores y arreglos nos<br />
hac<strong>en</strong> notar que la <strong>de</strong>finición <strong>de</strong> los argum<strong>en</strong>tos char s[]; y char *s; son<br />
completam<strong>en</strong>te equival<strong>en</strong>tes cuando se pasa un nombre <strong>de</strong> un arreglo <strong>de</strong><br />
caracteres a una función. Ya que al pasar un arreglo como parámetro, lo<br />
que <strong>en</strong> realidad se esta pasando es la dirección d<strong>el</strong> comi<strong>en</strong>zo d<strong>el</strong> mismo.<br />
Recor<strong>de</strong>mos la función carga() <strong>de</strong> nuestro ejemplo <strong>de</strong> un arreglo<br />
<strong>de</strong> números <strong>en</strong>teros.<br />
void carga(int &b){ // sin & funciona igual por que?<br />
for (int i = 0;i < 5;i++)<br />
cin>>b[i];<br />
}<br />
Si escribimos<br />
void carga(int * b){<br />
for (int i = 0;i < 5;i++)<br />
cin>>b[i];<br />
}<br />
o bi<strong>en</strong><br />
void carga(int * b){<br />
for (int i = 0;i < 5;i++)<br />
cin>>*b++;<br />
}<br />
<strong>en</strong> <strong>de</strong>finitiva y aceptando los conceptos <strong>de</strong> Brian y D<strong>en</strong>nis la variable<br />
original <strong>de</strong> tipo arreglo <strong>de</strong> <strong>en</strong>teros se verá modificada al producirse la<br />
carga <strong>de</strong> <strong>el</strong>em<strong>en</strong>tos, manipulando <strong>el</strong> arreglo a partir <strong>de</strong> subíndices o bi<strong>en</strong><br />
un puntero a <strong>en</strong>teros.<br />
3 Brian W. Kerninghan and D<strong>en</strong>nis M. Ritchie, El L<strong>en</strong>guaje <strong>de</strong> Programación C
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 13<br />
Ing. Ubaldo José Bonaparte<br />
modo:<br />
También podríamos haber escrito la función carga d<strong>el</strong> sigui<strong>en</strong>te<br />
void carga(int * b){<br />
for (int i = 0;*b == '\0';b++){<br />
i++;<br />
cin>>*b;<br />
}<br />
}<br />
siempre y cuando los <strong>el</strong>em<strong>en</strong>tos d<strong>el</strong> arreglo estén inicializados <strong>en</strong> cero,<br />
ya que <strong>de</strong> lo contrario t<strong>en</strong>dríamos algunos inconv<strong>en</strong>i<strong>en</strong>tes.<br />
Parámetros <strong>de</strong> tipo puntero o apuntadores siempre tomarán la<br />
dirección <strong>de</strong> la variable original, por consecu<strong>en</strong>cia la refer<strong>en</strong>cia a la<br />
misma.<br />
Los parámetros por refer<strong>en</strong>cia puntero pued<strong>en</strong> t<strong>en</strong>er <strong>el</strong> mismo<br />
cometido que los por refer<strong>en</strong>cia, solo <strong>en</strong> <strong>el</strong> concepto que al modificar un<br />
argum<strong>en</strong>to, se afectará al parámetro. Pero no <strong>en</strong> su tratami<strong>en</strong>to, don<strong>de</strong> se<br />
trabaja siempre sobre la base <strong>de</strong> la aritmética <strong>de</strong> punteros.<br />
Completemos la i<strong>de</strong>a, con un ejemplo s<strong>en</strong>cillo:<br />
#inclu<strong>de</strong> <br />
void increm<strong>en</strong>ta(int *b) {<br />
(*b)++;<br />
}<br />
void main(void){<br />
int a = 4;<br />
increm<strong>en</strong>ta(&a);<br />
cout
14- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
void increm<strong>en</strong>ta(int *b) {<br />
(*b)++;<br />
}<br />
void main(void){<br />
int a = 4; int * ptero;<br />
ptero = &a;<br />
increm<strong>en</strong>ta(ptero);<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 15<br />
Ing. Ubaldo José Bonaparte<br />
}<br />
void main(){<br />
matriz m = {0,0,0,0};<br />
cargapuntero(&m[0][0]);<br />
muestra(m);<br />
printf("\nLa suma <strong>de</strong> los <strong>el</strong>em<strong>en</strong>tos es = %d\n",suma(m));<br />
}<br />
Al trabajar con una variable subindizada y bidim<strong>en</strong>sional cuando<br />
invocamos a la función carga(), <strong>de</strong>bemos pasarle como parámetro la<br />
dirección <strong>de</strong> la variable local <strong>en</strong>tera m (&m[0][0]), para tratar la matriz<br />
con punteros. El argum<strong>en</strong>to <strong>de</strong> la función carga(), recibe dicha dirección<br />
sobre una variable <strong>de</strong> tipo puntero a un <strong>en</strong>tero a, y manipula las<br />
direcciones <strong>de</strong> memoria <strong>de</strong> la matriz m con la aritmética <strong>de</strong> punteros<br />
aplicada a dicha variable.<br />
Combinando tipos <strong>de</strong> parámetros<br />
Al invocar funciones, po<strong>de</strong>mos hacerlo pasando parámetros <strong>de</strong><br />
distintos tipos e inclusive con tipos <strong>de</strong> variables difer<strong>en</strong>tes.<br />
Prototipos <strong>de</strong> funciones como ejemplos:<br />
double mayor( double a, double b);<br />
Para averiguar cual cont<strong>en</strong>ido <strong>de</strong> variable es mayor, <strong>el</strong> tipo <strong>de</strong><br />
parámetro solo <strong>de</strong>be ser por valor.<br />
double suma_uno_al_mayor(double &, double &);<br />
Si <strong>de</strong>seamos increm<strong>en</strong>tar al cont<strong>en</strong>ido <strong>de</strong> la variable mayor <strong>en</strong><br />
uno, <strong>de</strong>bemos t<strong>en</strong>er <strong>en</strong> cu<strong>en</strong>ta que se podrá modificar una u otra variable.<br />
De modo que <strong>el</strong> tipo <strong>de</strong> parámetro <strong>de</strong>be ser por refer<strong>en</strong>cia.<br />
void carga_datos( cha * nombre, int & edad, int tipo);
16- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Como tipo indicará alguna alternativa <strong>de</strong> ingreso <strong>de</strong> datos, <strong>el</strong><br />
parámetro es por valor. Y ya que <strong>el</strong> interés es afectar variables originales<br />
que respond<strong>en</strong> a un nombre y la edad, dichos parámetros son por<br />
refer<strong>en</strong>cia.<br />
int funcion(int, int &, char *, int *, float);<br />
Otras variantes <strong>de</strong> combinaciones <strong>de</strong> parámetros.<br />
La función main() y sus argum<strong>en</strong>tos.<br />
Los parámetros pasados <strong>en</strong> la línea <strong>de</strong> órd<strong>en</strong>es d<strong>el</strong> DOS o líneas<br />
<strong>de</strong> comandos d<strong>el</strong> Windows a un programa, son recibidos por la<br />
función main() sobre sus argum<strong>en</strong>tos. Exist<strong>en</strong> dos variables pre<strong>de</strong>finidas<br />
d<strong>en</strong>tro d<strong>el</strong> l<strong>en</strong>guaje que recib<strong>en</strong> los argum<strong>en</strong>tos que se pasan al ejecutar<br />
un programa.<br />
Tipo<br />
Finalidad<br />
conti<strong>en</strong>e <strong>el</strong> número <strong>de</strong> argum<strong>en</strong>tos que se han<br />
argc <strong>en</strong>tero<br />
introducido mas uno.<br />
argv array array <strong>de</strong> punteros a caracteres.<br />
El argv conti<strong>en</strong>e los parámetros que se han pasado <strong>de</strong>s<strong>de</strong> <strong>el</strong><br />
sistema operativo al invocar <strong>el</strong> programa. La <strong>de</strong>claración <strong>de</strong> los<br />
argum<strong>en</strong>tos es:<br />
La variable argc como mínimo valdrá 1, ya que <strong>el</strong> nombre d<strong>el</strong><br />
programa se toma como primer parámetro, almac<strong>en</strong>ado con argv[0], que<br />
es <strong>el</strong> primer <strong>el</strong>em<strong>en</strong>to <strong>de</strong> la matriz. Cada <strong>el</strong>em<strong>en</strong>to d<strong>el</strong> array apunta a un<br />
parámetro <strong>de</strong> la línea <strong>de</strong> órd<strong>en</strong>es. Todos los parámetros <strong>de</strong> la línea <strong>de</strong><br />
órd<strong>en</strong>es son cad<strong>en</strong>as.<br />
#inclu<strong>de</strong> <br />
void main(int argc, char *argv[]) {<br />
if(argc != 2){
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 17<br />
Ing. Ubaldo José Bonaparte<br />
printf("Ha olvidado su nombre.\n");<br />
return;}<br />
printf("Hola %s", argv[1]);<br />
printf("Parámetros d<strong>el</strong> usuario %d", argc);<br />
}<br />
Este programa imprime Hola y su nombre <strong>en</strong> la pantalla si se<br />
escribe directam<strong>en</strong>te tras <strong>el</strong> nombre d<strong>el</strong> programa. Supongamos que<br />
hemos llamado al programa saludo.cpp, <strong>en</strong>tonces, al compilarlo se creará<br />
un ejecutable saludo.exe, al llamar al programa saludo con un nombre,<br />
por ejemplo:Juan, para ejecutar <strong>el</strong> programa t<strong>en</strong>drá que introducir<br />
c:\tcwin\bin\saludo Juan<br />
Y la salida d<strong>el</strong> programa sería<br />
Hola Juan<br />
Parámetros d<strong>el</strong> usuario 2.<br />
Observaremos para un nuevo ejemplo, que a pesar <strong>de</strong> no<br />
ejecutarse inicialm<strong>en</strong>te la función main(), ya que se ejecuta la función<br />
inicio (especificado por #pragma startup), <strong>el</strong> comportami<strong>en</strong>to <strong>de</strong> los<br />
parámetros es igual al ejemplo anterior.<br />
#inclu<strong>de</strong> <br />
void inicio(void){<br />
printf("Com<strong>en</strong>zo la ejecución\n");<br />
}<br />
void fin(void){<br />
printf("\nTermino la ejecución\n");<br />
}<br />
#pragma startup inicio<br />
#pragma exit fin<br />
void main(int argc, char *argv[]) {<br />
if(argc < 2){<br />
printf("Ha olvidado su nombre.\n");
18- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
return; }<br />
<strong>el</strong>se<br />
printf("Hola %s\n", argv[1]);<br />
printf("Parametros %d", argc);<br />
}<br />
En la mayoría <strong>de</strong> los <strong>en</strong>tornos, cada parámetro <strong>de</strong> la línea <strong>de</strong><br />
órd<strong>en</strong>es <strong>de</strong>be estar separado por un espacio o una tabulación. Las comas,<br />
puntos y comas, y similares no se consi<strong>de</strong>ran separadores. argv[0]<br />
conti<strong>en</strong>e <strong>el</strong> path (camino) y nombre d<strong>el</strong> programa que se esta ejecutando.<br />
Main() pue<strong>de</strong> no recibir parámetros si fue <strong>de</strong>finida como:<br />
main(void) {<br />
:<br />
:<br />
return(tipo_<strong>de</strong>_dato);<br />
}<br />
Variedad <strong>de</strong> ejemplos usando parámetros<br />
Vamos a observar una serie <strong>de</strong> ejemplos que utilizan los tres tipos<br />
<strong>de</strong> parámetros sobre argum<strong>en</strong>tos <strong>de</strong> tipos distintos.<br />
Ejemplo para una variable nativa simple, <strong>en</strong>tera:<br />
#inclu<strong>de</strong> <br />
void increm<strong>en</strong>ta_valor(int b) // por valor no afecta a la variable original a<br />
{ b++;}<br />
void increm<strong>en</strong>ta_refer<strong>en</strong>cia(int &b) // afecta a la variable original a<br />
{ b++;}<br />
void increm<strong>en</strong>ta_ref_puntero(int *b) // afecta a la variable original a<br />
{ (*b)++;} // la aritmética <strong>de</strong> punteros nos exige colocar los paréntesis.<br />
void main(void){<br />
int a = 4; // variable local <strong>de</strong> la función main<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 19<br />
Ing. Ubaldo José Bonaparte<br />
increm<strong>en</strong>ta_valor(a);<br />
cout
20- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
suma_ref_puntero(&b);<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 21<br />
Ing. Ubaldo José Bonaparte<br />
suma_ref_puntero(&b);<br />
cout
22- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 23<br />
Ing. Ubaldo José Bonaparte<br />
Ahora bi<strong>en</strong>, al pasar como parámetro la dirección <strong>de</strong> la variable a,<br />
<strong>de</strong>be ser recibida por un argum<strong>en</strong>to <strong>de</strong> tipo puntero a puntero <strong>de</strong> un<br />
<strong>en</strong>tero. En este caso toda modificación que se produzca sobre <strong>el</strong><br />
cont<strong>en</strong>ido d<strong>el</strong> argum<strong>en</strong>to afectará a la variable original.<br />
Para no afectar a la variable original, se <strong>de</strong>be pasar como<br />
parámetro <strong>el</strong> cont<strong>en</strong>ido <strong>de</strong> la misma increm<strong>en</strong>ta_valor(*a); que será<br />
recibido <strong>en</strong> un argum<strong>en</strong>to <strong>de</strong> tipo <strong>en</strong>tero.<br />
Variantes <strong>de</strong> parámetros y argum<strong>en</strong>tos<br />
Ya conocidos los tipos <strong>de</strong> parámetros básicos, po<strong>de</strong>mos ver<br />
algunas variantes que <strong>C++</strong> nos brinda como alternativas validas <strong>en</strong> la<br />
especificación <strong>de</strong> argum<strong>en</strong>tos <strong>de</strong> funciones.<br />
<strong>Argum<strong>en</strong>tos</strong> por <strong>de</strong>fecto (omisión)<br />
Una mejora <strong>de</strong> las funciones <strong>en</strong> <strong>C++</strong> es que se pued<strong>en</strong> especificar<br />
los valores por <strong>de</strong>fecto para los argum<strong>en</strong>tos cuando se proporciona un<br />
prototipo <strong>de</strong> una función. Cuando se llama a una función se pued<strong>en</strong><br />
omitir argum<strong>en</strong>tos e inicializarlos a un valor por <strong>de</strong>fecto.<br />
Un argum<strong>en</strong>to por <strong>de</strong>fecto u omisión es un parámetro que <strong>el</strong><br />
llamado a una función no va a proporcionar. Los argum<strong>en</strong>tos por <strong>de</strong>fecto<br />
también pued<strong>en</strong> ser parámetros opcionales. Si se pasa un valor a uno <strong>de</strong><br />
<strong>el</strong>los, se utiliza ese valor. Si no se pasa un valor a un parámetro opcional,<br />
se utiliza un valor por <strong>de</strong>fecto como argum<strong>en</strong>to.<br />
Ejemplo:<br />
#inclu<strong>de</strong> <br />
void f(int ,int = 2); // prototipo <strong>de</strong> función<br />
void main(){<br />
f(4,5);
24- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
f(6);<br />
}<br />
void f(int i, int j){<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 25<br />
Ing. Ubaldo José Bonaparte<br />
ver(cad,cad<strong>en</strong>a);<br />
}<br />
void ver( void *p, dato d){<br />
switch(d){<br />
case caracter: printf("%c\n",*(char *)p);<br />
break;<br />
case <strong>en</strong>tero: printf("%d\n",*(int *)p);<br />
break;<br />
case real: printf("%ld\n",*(double *)p);<br />
break;<br />
case cad<strong>en</strong>a: printf("%s\n",(char *)p);<br />
}<br />
}<br />
El argum<strong>en</strong>to void *p recibe <strong>el</strong> parámetro <strong>en</strong>viado <strong>de</strong>sconoci<strong>en</strong>do<br />
<strong>el</strong> tipo, lo cual es indisp<strong>en</strong>sable <strong>de</strong> especificar para direccionar, como <strong>en</strong><br />
<strong>el</strong> printf() <strong>de</strong> la función ver() *(char *)p, <strong>en</strong> <strong>el</strong> caso <strong>de</strong> ser un caracter. En<br />
este caso nos apoyamos sobre <strong>el</strong> <strong>en</strong>umerado dato, para id<strong>en</strong>tificar <strong>el</strong> tipo<br />
al que apunta *p.<br />
<strong>Argum<strong>en</strong>tos</strong> no especificados o variables<br />
<strong>C++</strong> permite <strong>de</strong>clarar una función cuyo número y tipo <strong>de</strong><br />
argum<strong>en</strong>tos no son conocidos <strong>en</strong> <strong>el</strong> mom<strong>en</strong>to <strong>de</strong> la compilación. Esta<br />
característica se indica con la ayuda d<strong>el</strong> operador especial puntos<br />
susp<strong>en</strong>sivos (...) <strong>en</strong> la <strong>de</strong>claración <strong>de</strong> la función. void f1(...);<br />
Esta <strong>de</strong>claración indica que f1 es una función que no <strong>de</strong>vu<strong>el</strong>ve<br />
ningún valor y que tomará un número variable <strong>de</strong> argum<strong>en</strong>tos <strong>en</strong> cada<br />
llamada. Si algunos argum<strong>en</strong>tos se conoc<strong>en</strong>, <strong>de</strong>b<strong>en</strong> situarse al principio<br />
<strong>de</strong> la lista:<br />
void f2(int a,float b,...);<br />
Los puntos susp<strong>en</strong>sivos indican que la función se pue<strong>de</strong> llamar<br />
con difer<strong>en</strong>tes conjuntos <strong>de</strong> argum<strong>en</strong>tos <strong>en</strong> distintas ocasiones. Este
26- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
formato <strong>de</strong> prototipo reduce la cantidad <strong>de</strong> verificación que <strong>el</strong> compilador<br />
realiza.<br />
Así, la función pre<strong>de</strong>finida printf(), que ti<strong>en</strong>e <strong>el</strong> prototipo:<br />
int printf(char *formato,...);<br />
Esto significa que la función <strong>de</strong>vu<strong>el</strong>ve un <strong>en</strong>tero y acepta un<br />
puntero a un parámetro fijo <strong>de</strong> caracteres y cualquier número <strong>de</strong><br />
parámetros adicionales <strong>de</strong> tipo <strong>de</strong>sconocido. Con este prototipo, <strong>el</strong><br />
compilador verifica <strong>en</strong> tiempo <strong>de</strong> compilación los parámetros fijos, y los<br />
parámetros variables se pasan sin verificación <strong>de</strong> tipos.<br />
Para <strong>en</strong>t<strong>en</strong><strong>de</strong>r cómo es posible crear este tipo <strong>de</strong> funciones con<br />
parámetros variables, es interesante compr<strong>en</strong><strong>de</strong>r aunque sólo sea <strong>de</strong><br />
manera superficial, cómo funciona un compilador. En especial <strong>el</strong><br />
mecanismo <strong>de</strong> llamadas a funciones.<br />
Cuando <strong>el</strong> compilador traduce <strong>el</strong> código fu<strong>en</strong>te a código máquina<br />
utiliza una pila para realizar ciertas tareas. La pila es, básicam<strong>en</strong>te, una<br />
zona <strong>de</strong> almac<strong>en</strong>ami<strong>en</strong>to temporal <strong>en</strong> memoria a la cual se hace<br />
refer<strong>en</strong>cia con un puntero. A través <strong>de</strong> este puntero se pue<strong>de</strong> conocer sus<br />
cont<strong>en</strong>idos. Cuando se llama a una función, se crea una nueva zona <strong>en</strong><br />
<strong>el</strong>la (un frame) don<strong>de</strong> se almac<strong>en</strong>a cierta información, como por ejemplo,<br />
la dirección <strong>de</strong> retorno, las variables automáticas <strong>de</strong> la función, etc. A<br />
nosotros, lo que nos interesa es que <strong>en</strong> esa zona, también se copian los<br />
argum<strong>en</strong>tos <strong>de</strong> la función.<br />
En C los argum<strong>en</strong>tos se pasan por valor, es <strong>de</strong>cir, se hac<strong>en</strong> copias<br />
<strong>de</strong> los mismos, y por eso po<strong>de</strong>mos usarlos como variables d<strong>en</strong>tro d<strong>el</strong><br />
cuerpo <strong>de</strong> la función, sin miedo a que varí<strong>en</strong> fuera, y <strong>de</strong>bemos trabajar<br />
con punteros cuando queremos <strong>el</strong> comportami<strong>en</strong>to contrario, es <strong>de</strong>cir <strong>el</strong><br />
paso <strong>de</strong> argum<strong>en</strong>tos por refer<strong>en</strong>cia.<br />
Veamos un caso s<strong>en</strong>cillo. T<strong>en</strong>emos la sigui<strong>en</strong>te función y<br />
llamada:
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 27<br />
Ing. Ubaldo José Bonaparte<br />
void funcion(int a, int b);<br />
funcion(10, 20);<br />
En <strong>el</strong> frame <strong>de</strong> la pila t<strong>en</strong>dremos los valores <strong>de</strong> dichas variables.<br />
Por lo tanto, si la dirección <strong>de</strong> memoria d<strong>el</strong> primer parámetro es X, <strong>el</strong><br />
cont<strong>en</strong>ido [X] es 10 –<strong>en</strong> ad<strong>el</strong>ante, usaré la conv<strong>en</strong>ción <strong>de</strong> los corchetes<br />
para indicar <strong>el</strong> cont<strong>en</strong>ido <strong>de</strong> una posición <strong>de</strong> memoria-. A<strong>de</strong>más, <strong>el</strong><br />
segundo parámetro estará <strong>en</strong> XXXX+sizeof(int), por<br />
tanto [X+sizeof(int)] es 20.<br />
Parece claro que las variables están contiguas <strong>en</strong> memoria. Si<br />
t<strong>en</strong>emos ahora una función y la llamada:<br />
void funcion(char *s , ... );<br />
funcion("Estos son dos<br />
números: %d y %f", 10, 0.5);<br />
Entonces, como vimos antes, sabemos que [X], por ser un puntero<br />
conti<strong>en</strong>e la dirección <strong>de</strong> memoria don<strong>de</strong> se almac<strong>en</strong>a la letra 'E'. Pero<br />
a<strong>de</strong>más, sabemos que <strong>de</strong> existir otro parámetro este estaría <strong>en</strong> la<br />
posición X+sizeof(char *), y que <strong>el</strong> sigui<strong>en</strong>te estaría <strong>en</strong>X+sizeof(char<br />
*)+sizeof(tipo) -<strong>el</strong> tipo es <strong>de</strong>sconocido a priori-. Es aritmética <strong>de</strong><br />
punteros pura. De este modo, es s<strong>en</strong>cillo obt<strong>en</strong>er todos los argum<strong>en</strong>tos<br />
que se pas<strong>en</strong> a la función, sin importar cuantos sean ni <strong>de</strong> que tipo.<br />
En realidad, esto no ti<strong>en</strong>e porque suce<strong>de</strong>r <strong>de</strong> este modo tan i<strong>de</strong>al,<br />
<strong>de</strong>p<strong>en</strong><strong>de</strong>rá <strong>de</strong> la arquitectura, <strong>el</strong> sistema operativo, <strong>el</strong> compilador, etc. Sin<br />
embargo, este mod<strong>el</strong>o <strong>de</strong> posiciones contiguas para los argum<strong>en</strong>tos es la<br />
base d<strong>el</strong> sistema que usa C, y ayudará al lector a <strong>en</strong>t<strong>en</strong><strong>de</strong>r <strong>el</strong> mecanismo<br />
que se nos proporciona.
28- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
El archivo stdarg.h conti<strong>en</strong>e macros que se pued<strong>en</strong> utilizar <strong>en</strong><br />
funciones <strong>de</strong>finidas por <strong>el</strong> usuario con número variable <strong>de</strong> parámetros.<br />
En <strong>C++</strong> hay otro método para proporcionar argum<strong>en</strong>tos a<br />
funciones que ti<strong>en</strong><strong>en</strong> listas <strong>de</strong> argum<strong>en</strong>tos <strong>en</strong> número variable. Este<br />
método facilita al compilador toda la información necesaria <strong>en</strong> una lista<br />
con un número variable <strong>de</strong> argum<strong>en</strong>tos, proporcionándole un conjunto <strong>de</strong><br />
variables preescritas que le indican cuántos argum<strong>en</strong>tos conti<strong>en</strong>e la lista y<br />
qué tipo <strong>de</strong> datos son.<br />
Las macros que se pued<strong>en</strong> utilizar para este propósito están<br />
<strong>de</strong>finidas <strong>en</strong> un archivo <strong>de</strong> cabecera d<strong>en</strong>ominado stdarg.h y<br />
son va_start(), va_arg() y va_<strong>en</strong>d().<br />
Las macros d<strong>el</strong> archivo stdarg.h ti<strong>en</strong><strong>en</strong> dos características útiles:<br />
- Han sido escritas para uso d<strong>el</strong> programador y son bastantes versátiles,<br />
<strong>de</strong> modo que se pued<strong>en</strong> utilizar <strong>de</strong> diversas formas.<br />
- Las macros proporcionan un medio transportables para pasar<br />
argum<strong>en</strong>tos variables. Esto se <strong>de</strong>be a que están disponibles dos versiones<br />
<strong>de</strong> macros: las <strong>de</strong>finidas <strong>en</strong> stdarg.h, que sigu<strong>en</strong> <strong>el</strong> standard ANSI C, y<br />
las <strong>de</strong>finidas <strong>en</strong> varargs.h, que son compatibles con UNIXSystem V.<br />
La macro va_list es un tipo <strong>de</strong> dato que es equival<strong>en</strong>te a una lista<br />
<strong>de</strong> variables. Una vez que se <strong>de</strong>fine una variable va_list, se pue<strong>de</strong> utilizar<br />
como un parámetro <strong>de</strong> las macros va_start()y va_<strong>en</strong>d().<br />
La sintaxis <strong>de</strong> la macro va_start() es: void va_start(va_list<br />
arg_ptr, prev_param); arg_ptr apunta al primer argum<strong>en</strong>to opcional <strong>en</strong><br />
una lista variable <strong>de</strong> argum<strong>en</strong>tos pasados a una función. Si la lista <strong>de</strong><br />
argum<strong>en</strong>tos <strong>de</strong> una función conti<strong>en</strong>e parámetros que se han especificado<br />
<strong>en</strong> la <strong>de</strong>claración <strong>de</strong> la función, <strong>el</strong> argum<strong>en</strong>to prev_param <strong>de</strong> va_start()<br />
proporciona <strong>el</strong> nombre d<strong>el</strong> argum<strong>en</strong>to especificado <strong>de</strong> la función que<br />
prece<strong>de</strong> inmediatam<strong>en</strong>te al primer argum<strong>en</strong>to opcional <strong>de</strong> la lista <strong>de</strong><br />
argum<strong>en</strong>tos.
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 29<br />
Ing. Ubaldo José Bonaparte<br />
Cuando la macro va_start() se ejecuta, hace que <strong>el</strong> parámetro<br />
arg_ptr apunte al argum<strong>en</strong>to especificado por prev_param.<br />
La sintaxis <strong>de</strong> la macro va_arg() es: void va_arg(va_list<br />
arg_ptr,tipo);<br />
La macro va_arg() ti<strong>en</strong>e un propósito doble:<br />
- Primero, va_arg() <strong>de</strong>vu<strong>el</strong>ve <strong>el</strong> valor d<strong>el</strong> objeto apuntado por <strong>el</strong><br />
argum<strong>en</strong>to arg_ptr.<br />
- Segundo, va_arg() increm<strong>en</strong>ta arg_ptr para apuntar al sigui<strong>en</strong>te<br />
<strong>el</strong>em<strong>en</strong>to <strong>de</strong> la lista variable <strong>de</strong> argum<strong>en</strong>tos <strong>de</strong> la función que se está<br />
llamando, utilizando <strong>el</strong> tamaño tipo para <strong>de</strong>terminar dón<strong>de</strong> comi<strong>en</strong>za <strong>el</strong><br />
sigui<strong>en</strong>te argum<strong>en</strong>to.<br />
La sintaxis <strong>de</strong> la macro va_<strong>en</strong>d() es: void va_<strong>en</strong>d(va_list<br />
arg_ptr);<br />
La macro va_<strong>en</strong>d() realiza las tareas auxiliares que son necesarias<br />
para que la función llamada retorne correctam<strong>en</strong>te. Cuando todos los<br />
argum<strong>en</strong>tos se le<strong>en</strong>, va_<strong>en</strong>d() reinicializa arg_ptr a NULL.<br />
El pseudocódigo d<strong>el</strong> proceso para manejar la lista variable <strong>de</strong><br />
argum<strong>en</strong>tos sería:<br />
tipo funcionVariable(last , ...) {<br />
va_list pa;<br />
tipo_X argum<strong>en</strong>to_<strong>de</strong>_tipo_X;<br />
va_start(pa,last);<br />
while (quedan<strong>Argum<strong>en</strong>tos</strong>)<br />
argum<strong>en</strong>to_<strong>de</strong>_tipo_X = va_arg(pa, tipo_X);<br />
va_<strong>en</strong>d(pa);<br />
}<br />
El ord<strong>en</strong> es innegociable. Debe <strong>de</strong>finirse <strong>el</strong> puntero <strong>de</strong> tipo va_list<br />
que se <strong>de</strong>be inicializar con va_start para po<strong>de</strong>r com<strong>en</strong>zar a trabajar.
30- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
Mi<strong>en</strong>tras haya argum<strong>en</strong>tos, hay que obt<strong>en</strong>erlos con va_arg y para<br />
terminar, hay que llamar siempre a va_<strong>en</strong>d.<br />
Hay que prestar at<strong>en</strong>ción a unos <strong>de</strong>talles cuando usemos este tipo <strong>de</strong><br />
construcciones.<br />
1. La lista variable siempre va al final <strong>de</strong> los argum<strong>en</strong>tos.<br />
2. Ti<strong>en</strong>e que haber al m<strong>en</strong>os un argum<strong>en</strong>to <strong>de</strong>finido (last), para<br />
po<strong>de</strong>r t<strong>en</strong>er una refer<strong>en</strong>cia y acce<strong>de</strong>r al resto <strong>de</strong> argum<strong>en</strong>tos.<br />
3. Dado que la dirección <strong>de</strong> last es utilizada por va_start no <strong>de</strong>be ser<br />
ni una variable register, ni una función, ni un array.<br />
4. Si no hay próximo argum<strong>en</strong>to, o si tipo no es compatible con <strong>el</strong><br />
tipo d<strong>el</strong> próximo argum<strong>en</strong>to, se producirán errores impre<strong>de</strong>cibles<br />
al llamar a va_arg.<br />
5. Cuidado con los tipos. T<strong>en</strong>gan <strong>en</strong> cu<strong>en</strong>ta que por <strong>de</strong>fecto C hace<br />
promoción <strong>de</strong> los parámetros pasados, así, si pasan un float, este<br />
será promovido a double y la s<strong>en</strong>t<strong>en</strong>cia va_arg(pa,float) será<br />
incorrecta. Lo mismo con shorts, etc. Normalm<strong>en</strong>te <strong>el</strong> compilador<br />
nos avisará <strong>de</strong> esto.<br />
6. Las macros nos ayudan a trabajar <strong>de</strong> modo portable. No importa,<br />
por ejemplo, que un int t<strong>en</strong>ga 32 o 16 bits. Las macros y <strong>el</strong><br />
compilador se <strong>en</strong>cargan <strong>de</strong> resolver la difer<strong>en</strong>cia. Nosotros sólo<br />
vemos una lista <strong>de</strong> variables <strong>de</strong> distintos tipos.<br />
Como controlar <strong>el</strong> número <strong>de</strong> argum<strong>en</strong>tos<br />
Controlar <strong>el</strong> número <strong>de</strong> argum<strong>en</strong>tos es importante para evitar<br />
errores. Pongamos como ejemplo algo muy habitual cuando se nos<br />
escapa un <strong>de</strong>talle: equivocarnos <strong>en</strong> un printf. Si escribimos lo sigui<strong>en</strong>te:<br />
printf("%d %d %d\n", 3, 4, 5, 6);<br />
printf("%d %d %d\n", 3, 4); // error 3 imág<strong>en</strong>es para 2 datos<br />
obt<strong>en</strong>dremos la salida, don<strong>de</strong> <strong>el</strong> último número pue<strong>de</strong> variar <strong>de</strong> una<br />
sistema operativo a otro.<br />
3 4 5<br />
3 4 134513729
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 31<br />
Ing. Ubaldo José Bonaparte<br />
Pasarse <strong>en</strong> <strong>el</strong> número <strong>de</strong> argum<strong>en</strong>tos no parece muy problemático,<br />
sin embargo, quedarse corto provoca resultados extraños. El compilador<br />
está buscando un <strong>en</strong>tero pero <strong>en</strong>cu<strong>en</strong>tra memoria sin inicializar (basura)<br />
que <strong>en</strong> este caso particular equivale a un 134513729, si se interpreta<br />
como un <strong>en</strong>tero.<br />
Hay que t<strong>en</strong>er mucho cuidado. En este s<strong>en</strong>cillo ejemplo, t<strong>en</strong>emos<br />
un problema visual, que no parece muy grave. ¿Y si <strong>el</strong> argum<strong>en</strong>to fuese<br />
un puntero? los efectos colaterales podrían ser terribles, podríamos t<strong>en</strong>er<br />
un error <strong>de</strong> segm<strong>en</strong>to o uno <strong>de</strong> esos bugs casi imposibles <strong>de</strong> <strong>de</strong>purar.<br />
De todos modos, parece que stdarg.h nos ofrece un mecanismo un<br />
poco escaso. Sería mejor disponer <strong>de</strong> algo similar a los argum<strong>en</strong>tos <strong>de</strong><br />
línea <strong>de</strong> comandos <strong>en</strong> main(int argc y char* argv[]), o al m<strong>en</strong>os t<strong>en</strong>er una<br />
macro va_count, o similar, que nos exprese cuántos argum<strong>en</strong>tos t<strong>en</strong>emos.<br />
Por <strong>de</strong>sgracia no es así y t<strong>en</strong>emos que usar otra aproximación don<strong>de</strong>,<br />
como programadores, t<strong>en</strong>emos que hacer explícito <strong>el</strong> número <strong>de</strong> los<br />
mismos.<br />
En g<strong>en</strong>eral, hay dos modos <strong>de</strong> hacerlo:<br />
1. Con un contador... uno <strong>de</strong> los argum<strong>en</strong>tos fijos es un <strong>en</strong>tero que<br />
indica <strong>el</strong> número <strong>de</strong> argum<strong>en</strong>tos variables que <strong>de</strong>bemos esperar.<br />
No permite indicar <strong>el</strong> tipo <strong>de</strong> los argum<strong>en</strong>tos a m<strong>en</strong>os que usemos<br />
un artificio adicional (como indicarlos con constantes<br />
simbólicas). Su<strong>el</strong>e usarse con funciones que recib<strong>en</strong> argum<strong>en</strong>tos<br />
<strong>de</strong> un tipo concreto.<br />
2. Con una cad<strong>en</strong>a <strong>de</strong> formateo... <strong>el</strong> estilo que usa la familia <strong>de</strong><br />
funciones printf y scanf. La función recibe un argum<strong>en</strong>to que<br />
indica <strong>de</strong> alguna manera la cantidad <strong>de</strong> argum<strong>en</strong>tos variables<br />
esperados y <strong>el</strong> tipo <strong>de</strong> los mismos.<br />
Ejemplo Nº 1:<br />
#inclu<strong>de</strong> <br />
#inclu<strong>de</strong> <br />
int suma_<strong>en</strong>teros(int primero,...);
32- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
void main(){<br />
cout
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 33<br />
Ing. Ubaldo José Bonaparte<br />
}<br />
return resultado;<br />
void pprintf(char *formato, ...) {<br />
char *p;<br />
va_list pa;<br />
va_start(pa, formato);<br />
for (p = formato; *p; p++) {<br />
if (*p != '?') {<br />
putchar (*p);<br />
continue;<br />
}<br />
switch (*++p) {<br />
case 'd':<br />
printf("{%d}", va_arg(pa, int));<br />
break;<br />
case 's':<br />
printf("{%s}", va_arg(pa, char *));<br />
break;<br />
<strong>de</strong>fault:<br />
putchar(*p);<br />
break;<br />
}<br />
}<br />
va_<strong>en</strong>d(pa);<br />
}<br />
int main (void) {<br />
printf("Resultado es %g\n", suma_reales(3, 0.3,0.1, 0.2));<br />
pprintf("Probemos a poner llaves a una ?s y a un ?d \n", "cad<strong>en</strong>a", 25);<br />
return 0;<br />
}<br />
La función suma_reales() muy similar a la función<br />
suma_<strong>en</strong>teros() d<strong>el</strong> ejemplo anterior, recibe como parámetros un <strong>en</strong>tero<br />
que indica la cantidad <strong>de</strong> argum<strong>en</strong>tos variables a buscar <strong>en</strong> la pila y una<br />
lista <strong>de</strong> argum<strong>en</strong>tos variables <strong>de</strong> tipos double.
34- Ciclo <strong>de</strong> Seminarios y Talleres d<strong>el</strong> Area <strong>de</strong> Programación.<br />
Parámetros y <strong>Argum<strong>en</strong>tos</strong> <strong>en</strong> <strong>el</strong> l<strong>en</strong>guaje <strong>de</strong> programación <strong>C++</strong>.<br />
La función pprintf() que recibe un puntero a una cad<strong>en</strong>a como<br />
parámetro (formato), don<strong>de</strong> pa <strong>de</strong> tipo va_list apuntará al primer carácter<br />
<strong>de</strong> la misma (“P”) y una lista variable <strong>de</strong> argum<strong>en</strong>tos a <strong>en</strong>contrar con<br />
va_arg(pa, tipo).<br />
Se produce la salida <strong>de</strong> caracteres hasta <strong>en</strong>contrar <strong>el</strong> carácter ?, <strong>el</strong><br />
cual seguido <strong>de</strong> una d establece que se busque <strong>el</strong> sigui<strong>en</strong>te argum<strong>en</strong>to <strong>de</strong><br />
tipo <strong>en</strong>tero y seguido <strong>de</strong> una s un argum<strong>en</strong>to <strong>de</strong> tipo cad<strong>en</strong>a, que nos<br />
<strong>de</strong>vu<strong>el</strong>ve va_arg() y se imprim<strong>en</strong>.
UTN, FRT, Departam<strong>en</strong>to <strong>de</strong> Sistemas <strong>de</strong> Información- 35<br />
Ing. Ubaldo José Bonaparte<br />
Conclusiones:<br />
Los parámetros juegan un pap<strong>el</strong> <strong>de</strong>masiado importante <strong>en</strong> los<br />
<strong>de</strong>sarrollos, don<strong>de</strong> <strong>el</strong> programador haci<strong>en</strong>do <strong>el</strong> uso a<strong>de</strong>cuado <strong>de</strong> los<br />
mismos, alim<strong>en</strong>tará <strong>el</strong> bu<strong>en</strong> hábito <strong>de</strong> controlar exhaustivam<strong>en</strong>te la<br />
persist<strong>en</strong>cia y manipulación <strong>de</strong> sus variables u objetos y como<br />
consecu<strong>en</strong>cia mant<strong>en</strong>drá distancia <strong>de</strong> los efectos colaterales.<br />
En la actualidad, la programación con l<strong>en</strong>guajes como Java, J#,<br />
.Net, C# y otros, continua sobre la base <strong>de</strong> los conceptos expuestos. De<br />
modo tal que recom<strong>en</strong>damos este artículo, especialm<strong>en</strong>te a principiantes<br />
que <strong>de</strong>se<strong>en</strong> manejar cuidadosam<strong>en</strong>te los parámetros y argum<strong>en</strong>tos.<br />
Bibliografía principal:<br />
- El L<strong>en</strong>guaje <strong>de</strong> Programación C, Brian W. Kernighan y D<strong>en</strong>nis M.<br />
Ritchie.<br />
- El <strong>C++</strong> L<strong>en</strong>guaje <strong>de</strong> Programación, Bjarne Stroustrup.<br />
- Programación y resolución <strong>de</strong> problemas <strong>en</strong> <strong>C++</strong>, N<strong>el</strong>l Dale y Chip<br />
Weems