<!-- Introdução à Programação - 2017 - Prof. Leoônidas de Oliveira Brandão Introdução ao conceito de parâmetros para funções LInE (Laboratory of Informatics in Education) - http://www.usp.br/line IME - USP Material didático Pode usar livrevemente este material para fins não comerciais, devendo sempre fazer referência à autoria. Sugestões/apontamento são bem vindos: leo@ime.usp.br (favor indicar no assunto "material de introducao 'a programacao") Prof. Leônidas de Oliveira Brandão http://www.ime.usp.br/~leo http://line.ime.usp.br http://www.matemtica.br @versao: versão inicial: 2011/06/10 --> <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'> <meta name='keywords' content='mac0122, material, professores, leonidas de oliveira brandao'> <link rel='stylesheet' type='text/css' href='css_img_js_conf/all.css'> <link rel='stylesheet' type='text/css' href='css_img_js_conf/line_introducao_programacao.css'> <script src="css_img_js_conf/defineLInE.js"></script> <!-- para referencias 'a documentos internos --> <div class="pagina"> <p class="secao">Introdução ao conceito de parâmetros para funções</p> <p> Neste texto, explicamos os princípios a respeito de passagem de parâmetros para <a href="#" onclick="trocaPagina('introducao_funcoes.html')" title="examinar o texto introdutório sobre funções em C e Python">funções</a>, particularmente diferenciando as passagens por <i>referência</i> (ou <i>endereço</i>) e por <i>valor</i>. </p> <!-- Leia com atenção estas observações a respeito de funções e passagem de parâmetros. Elas referem-se ao exemplo <a href="exemplo_referencia_valor.c" title="clique aqui para pegar o exemplos exemplo_referencia_valor.c">exemplo_referencia_valor.c</a>. --> <p class="subsecao">Por que parâmetros são necessários para funções?</p> <p> A <b style="color:#0000aa;">passagem de parâmetros</b> é essencial para ampliar o potencial de uso de uma função. Uma função sem parâmetro, é apenas um procedimento que executará sempre <i title="exceto se o programador estiver usando variáveis globais - mas esperamos que você jamais tente fazer dessa forma, pois um tal código seria muito mais difícil de ser depurado)">exatamente os mesmos passos</i>. Por exemplo, uma função para computar o fatorial de um número natural, deve ter um único parâmetro, digamos <i>n</i>, sendo que <i>n</i> deve conter o valor para o qual deseja-se saber o fatorial. Por um lado, na declaração da função deve-se indicar de alguma forma este parâmetro, que neste caso é denominado <b style="color:#0000aa;">parâmetro formal</b> (por ser um <i style="color:#0000aa;">formalismo</i> necessário para funcionar o conceito). <br/> Por outro lado, o ponto do código que "está interessado" no fatorial de algum valor é quem deve invocar a função passando-lhe esse valor como parâmetro, que neste caso recebe o nome de <b style="color:#0000aa;">parâmetro efetivo</b> (pois é <i style="color:#0000aa;">efetivamente</i> o valor sobre o qual dever ser "aplicada" a função). </p> <p> <center> <img src="img/exemplo_exec_funcao.jpg" title="exemplo de execucao da funcao"/> <br/> <i>Fig. 1. Ilustração do fluxo de execução ao <b>invocar</b> uma função para computar o <b>fatorial</b> de um natural.</i> </center> </p> <p> A figura 1 ilustra o exemplo da função fatorial, o código à esquerda está interessado em computar o fatorial de <i>N</i>, de <i>k</i> e de <i>N-k</i>, que são os <i>parâmtros efetivos</i> para a função <i>fat</i> do exemplo. Do lado direito está a código da função, sua declaração (usamos o nome <i>fat</i>) e seu único <i>parâmtro formal</i>, que recebeu o nome <i>n</i>. </p> <p class="subsubsecao">Introdução aos parâmetros formal e efetivo</p> <p> O conceito de funções apresenta 4 palavras-chave principais, que são: <ul> <li> <b>parâmetros formais</b>: usados na declaração da função (por isso denominados formais); <li> <b>parâmetros efetivos</b>: usados na chamada da função (quem invoca é quem deve providenciar os parâmetros <i>efetivamente</i> utilizados); <li> a passagem de parâmetros pode ser <ul> <li>por valor: como "a" e "b" em <tt>void funcao (<verm>int</verm> a, float b)</tt></li> <li>por referência: como "a" e "b" em <tt>void funcao (<verm>int</verm> *a, float b[])</tt></li> </ul> <li> em <i>C</i>, uma função devolve apenas tipos simples (como "int", "float" e "char"), nunca um vetor!!!</li> </ul> </p> <p> Assim, no caso de passagem de <b>parâmetro por referência</b> (ou <b>por endereço</b>), como o nome indica, será passada uma <b>referência</b> à uma variável <i>externa</i> à função (o parâmetro efetivo). Desse modo, dentro da função, ao alterar o valor do parâmetro formal, quem estará sendo alterado é efetivamente à variável <i>externa</i>. Em <i>C</i> existe uma sintaxe especial para declarar e alterar o parâmetro por referência (usando asterisco '<tt>*</tt>' - vide exemplo abaixo). </p> <p> Já o uso de <b>parâmetro por valor</b> é mais simples, o parâmetro formal funciona como uma <i>variável local</i> que é <i>inicializada</i> com o valor do parâmetro efetivo, assim que a função em questão é invocada. Qualquer alteração do parâmetro formal, tem influência nula sobre o parâmetro formal associado (ou seja, uma atribuição dentro da função com determinado parâmetro, não provoca alteração alguma no valor da variável que foi passada para a função - parâmetro efetivo). </p> <p> Nos exemplos abaixo ilustramos os 4 conceitos em exemplos para <i>C</i> e para <i>Python</i>. <center><table style="border: 1px solid black;font-size:0.8em;"> <tr> <th style="background-color:#8aaada;align:center;">C</th><th style="background-color:#8aaada;align:center;">Python</th></tr> <tr><td><pre style="font-size:0.8em;"><verm>int</verm> soma (<verm>int</verm> a, <verm>int</verm> b) { <verm>int</verm> c = a+b; <cyan>// variavel local: sem relacao com 'main.c'!</cyan> return a+b; <cyan>// devolve a+b</cyan> } <verm>int</verm> soma_max (<verm>int</verm> a, <verm>int</verm> b, <verm>int</verm> *max) { if (a < b) *max = b; <cyan>// altera o valor da referencia (em quem invocou soma_max)</cyan> else *max = a; <cyan>// em caso de empate tanto faz...</cyan> return a+b; <cyan>// devolve a+b</cyan> } <verm>int</verm> main (void) { <verm>int</verm> a, b, c, maximo; <verd>scanf</verd>("%d %d", &a, &b); <cyan>// operador '&' pega o endereco da variavel na memoria</cyan> c = soma_max(a,b,&maximo); <verd>print</verd>("Soma de %d e %d = %d = %d.\n", a, b, soma(a,b), c); <verd>print</verd>("O maximo e': %d\n", maximo); return 1; }</pre> </td><td><pre style="font-size:0.8em;"><verm>def</verm> soma (a, b) : c = a+b; <cyan># variavel local: sem relacao com 'main.c'!</cyan> return a+b; <cyan># devolve a+b</cyan> <verm>def</verm> soma_max (a, b, max) : if (a < b) : max[0] = b; <cyan># altera o valor da referencia (em quem invocou soma_max)</cyan> else : max[0] = a; <cyan># em caso de empate tanto faz...</cyan> return a+b; <cyan># devolve a+b</cyan> <verm>def</verm> main () : a = int(<verd>input</verd>()); b = int(<verd>input</verd>()); maximo = []; maximo.append(-1); <cyan># truque: usar vetor para param. por ref.</cyan> c = soma_max(a, b, maximo); <verd>print</verd>("Soma de %d e %d = %d = %d." % (a, b, soma(a,b), c)); <verd>print</verd>("O maximo e': %d" % (maximo[0])); main();</pre> </td></tr> </table></center> </p> <p class="subsubsecao">Explicações sobre as diferenças entre parâmetros por referência e por valor</p> <p> A diferença entre passagem de parâmetro por referência ou valor, no primeiro caso é passado o endereço (ou referência) da variável efetivamente usada (parâmetro efetivo) e no segundo o valor da variável efetivamente usada apenas serve como valor inicial para o parâmetro formal (uma <i>inicialização</i>). </p> <p> <i><b>C</b></i>: No código <i>C</i> acima, o que definiu tratar-se de referência foi o uso de '*' no parâmetro formal. Além disso, para fazer referência ao parâmetro efetivo (a variável <tt>maximo</tt>) também foi preciso usar o '*'. <br/> Por outro, na chamada da função foi preciso passar o endereço da variável <tt>maximo</tt> e isso foi possível usando o operador '&'. <br/> No exemplo não aparece, mas em <i>C</i>, ao passar um vetor como parâmetro, automaticamente ele é passador por referência. <br/> <a href="#" onclick="trocaPagina('introducao_funcoes_c.html')" title="Para examinar detalhes de funções C em clique aqui">Para examinar mais sobre funções em <i>C</i> clique aqui</a>. </p> <p> <i><b>Python</b></i>: No código <i>Python</i> acima, o que definiu tratar-se de referência foi usar como parâmetro formal um vetor (ou lista). Por isso foi preciso o "truque" de definir um vetor (de nome <tt>maximo</tt>, com um único elemento) e passá-lo como parâmetro efetivo para a função. <br/> Assim, em <i>Python</i>, sempre que passar um vetor como parâmetro, automaticamente ele é passador por referência. <br/> <a href="#" onclick="trocaPagina('introducao_funcoes_python.html')" title="Para examinar detalhes de funções em Python clique aqui">Para examinar mais sobre funções em <i>Python</i> clique aqui</a>. </p> <p> <a href="https://www.ime.usp.br/~leo" target="_blank" title="seguir para a pagina do prof. Leônidas">Leônidas de Oliveira Brandão</a><br/> <a href="http://www.ime.usp.br/~leo" target="_blank" title="seguir para a página do LInE">http://line.ime.usp.br</a> </p> <p class="rodape"> <b>Alterações</b>:<br/> 2020/08/20: acertos no formato<br/> 2020/08/10: revisão de formato e nova introdução<br/> 2020/08/09: Sábado, 09 de Agosto 2020, 14:00<br/> 2018/04/24: Terça, 24 de Abril 2018, 12:30<br/> 2011/06/10: inicial </p> </div>