nunopicado Posted October 3, 2011 at 09:00 PM Report #414482 Posted October 3, 2011 at 09:00 PM Ora então boa noite... Tenho reparado ao longo dos anos que este é um ponto de confusão para os programadores iniciantes (e até para alguns experientes) e como perceber isto é algo absolutamente essencial num programador a sério (e para os outros também), lembrei-me de iniciar este tópico. Vou aplicar isto a Pascal, mas a verdade é que o conceito é necessário em qualquer linguagem. Para quem não sabe, nos procedimentos e funções permitem a passagem de parâmetros (valores ou variáveis), que serão inseridos no momento da chamada desse procedimentou ou função, e serão transmitidos ao proprio código do procedimento ou função para por ele serem usados. Passagem por Parâmetro program parametro; var lado1,lado2:integer; function AreaRect(LadoMenor,LadoMaior:integer):integer; begin AreaRect:=LadoMenor*LadoMaior; end; begin Lado1:=6; Lado2:=4; Writeln(AreaRect(6,4),'cm2'); Writeln(AreaRect(Lado1,Lado2),'cm2'); end. Resultado (o que aparece no ecrã): 24cm2 24cm2 Aqui, LadoMenor e LadoMaior são duas variáveis passadas por parâmetro. Isto significa que o compilador gera duas variáveis dentro da função AreaRect, com os nomes LadoMenor e LadoMaior, e que quando a função é chamada, preenche essas variáveis com os valores indicados entre parentesis aquando da chamada da função. Neste caso, as variáveis podem ser usadas para qualquer fim dentro da função, e assumir qualquer valor do tipo indicado. No entanto, quando acaba a execução da função, qualquer valor que lá esteja é perdido. Por exemplo: program parametro; var valor1,valor2:integer; procedure DuplicaValores(v1,v2:integer); begin writeln('2º - Dentro: ',v1,' / ',v2); v1:=v1*2; v2:=v2*2; writeln('3º - Dentro: ',v1,' / ',v2); end; begin valor1:=6; valor2:=4; writeln('1º - Fora: ',valor1,' / ',valor2); DuplicaValores(valor1,valor2); writeln('4º - Fora: ',valor1,' / ',valor2); end. Resultado: 1º - Fora: 6 / 4 2º - Dentro: 6 / 4 3º - Dentro: 12 / 8 4º - Fora: 6 / 4 Por aqui se pode ver que: 1º Antes de executar o procedimento, os valores eram 6 e 4. 2º Dentro do procedimento, mas antes de proceder à multiplicação, os valores eram 6 e 4 (que foram copiados de fora para dentro do procedimento) 3º Dentro do procedimento, já depois de efectuar a multiplicação, os valores passaram a ser 12 e 8, ou seja, as variaveis v1 e v2 assumiram correctamente os valores que lhes foram atribuidos. 4º Uma vez fora do procedimento, as variaveis valor1 e valor2 continuam a mostrar os valores 6 e 4, ou seja, não refletem as alterações feitas dentro do procedimento. Portanto, isto mostra que a passagem por parâmetro é útil para enviar valores para dentro do procedimento, mas inútil para os trazer de dentro do procedimento para o local de chamada. É aqui que entra a passagem por referencia. Passagem por Referência A passagem por referência não cria duas variáveis com valores iguais aos que foram passados entre parentesis. O que ela faz é criar um atalho, dentro do procedimento ou função, para as variáveis originais. Deste modo, qualquer alteração feita dentro do procedimento é reflectida mesmo depois do procedimento ter terminado. Para exemplo, fica o programa anterior, com apenas uma pequena alteração: program parametro; var valor1,valor2:integer; procedure DuplicaValores(var v1,v2:integer); begin writeln('2º - Dentro: ',v1,' / ',v2); v1:=v1*2; v2:=v2*2; writeln('3º - Dentro: ',v1,' / ',v2); end; begin valor1:=6; valor2:=4; writeln('1º - Fora: ',valor1,' / ',valor2); DuplicaValores(valor1,valor2); writeln('4º - Fora: ',valor1,' / ',valor2); end. Resultado: 1º - Fora: 6 / 4 2º - Dentro: 6 / 4 3º - Dentro: 12 / 8 4º - Fora: 12 / 8 Apenas colocando a paravra chave VAR antes dos parâmetros do procedimento, indicamos ao compilador que as variáveis que se seguem são apenas atalhos para outras, e que deveram ter sempre o mesmo valor, tanto dentro como fora do procedimento ou função. Assim, o resultado final (4º) já depois de terminado o procedimento, manteve o valor multiplicado que se efectuou dentro do procedimento. Isto obriga no entanto a que os valores que colocamos entre parentesis sejam variáveis. Se com o procedimento indicado em cima usássemos... DuplicaValores(6,4); ...o compilador iria dar erro, pois está à espera de variáveis que possam receber valores. Números absolutos e constantes não são permitidas por este motivo. Do mesmo modo, usar na chamada uma variável, mas que não seja do mesmo tipo do declarado dentro do procedimento ou função, também iria ser gerado um erro: program erro; var x:real; procedure teste(var y:integer); begin writeln(y); end; begin x:=5.15; teste(x); end. Este código não iria funcionar. Daria um erro ao compilar, pois os tipos de variáveis são diferentes. Passagem por Parâmetro Constante Existe uma terceira hipotese, embora seja na verdade apenas uma variante da passagem por parâmetros. A única diferença é que em vez do compilador criar variáveis dentro do procedimento ou função, cria constantes, o que significa que mesmo dentro do procedimento ou função os seus valores não podem ser alterados. Espero que com isto seja mais fácil perceber a diferença e especialmente a importância destes conceitos para um programador. Se alguma duvida persistir, é só dizerem! "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
passarito Posted October 4, 2011 at 07:43 AM Report #414504 Posted October 4, 2011 at 07:43 AM Muito bom.... Lembro-me bem da dificuldade de entender este conceito quando andei a aprender pascal. Apenas deixar um pequeno promenor, uma dificuldade que me aconteceu quando estava a aprender este conceito. Agora parece-me bastante obvio, mas na altura.... Quando temos uma função ou procedimento com variaveis passadas por referencia, isto é, as que se podem modificar dentro das próprias, têm de ser chamadas com variaveis e não com valores fixos. Exemplo: Procedure fazqqcoisa(var x:integer); begin x:=x+1; end; ..... fazqqcoisa(5); {chamada inválida} fazqqcoisa(ab); {chamada válida se a variavel ab for tipo integer} Como disse agora parece-me bastante obvio.
nunopicado Posted October 4, 2011 at 07:46 AM Author Report #414505 Posted October 4, 2011 at 07:46 AM fazqqcoisa(5); {chamada inválida} hehehe Isso está lá, mas obrigado pelo reforço, é isso mesmo! 👍 fazqqcoisa(ab); {chamada válida se a variavel ab for tipo integer} Pois, isto não disse... A variável passada por referência deve obrigatoriamente ser do mesmo tipo da que está declarada no procedimento ou função! "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
nunopicado Posted October 4, 2011 at 08:53 AM Author Report #414511 Posted October 4, 2011 at 08:53 AM Obrigado M6 👍 "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
thoga31 Posted October 7, 2011 at 08:46 PM Report #415096 Posted October 7, 2011 at 08:46 PM Não tenho podido vir aqui nos últimos dias, mas amei este pequeno tutorial de Passagem por Parâmetro e por Referência. Os meus parabéns. Como sempre, explicas de forma excepcional, de tirar o chapéu. 😄 Assim que puder passarei para a Wiki. Se não te importares, vou fazer o link do Tutorial, quando falo de Procedimentos e Funções, para o teu documento. 😉 Faz falta estas pequenas coisas mas tão importantes! 😁 Knowledge is free!
nunopicado Posted October 7, 2011 at 08:49 PM Author Report #415097 Posted October 7, 2011 at 08:49 PM Está à vontade Thoga... Usa como entenderes! (e obrigado pelas palavras...) "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
thoga31 Posted October 7, 2011 at 09:24 PM Report #415106 Posted October 7, 2011 at 09:24 PM (e obrigado pelas palavras...) De nada. Palavras de mérito merecidas devem ser ditas por merecimento e não por obrigação. 😁 Knowledge is free!
pwseo Posted October 10, 2011 at 12:46 PM Report #415314 Posted October 10, 2011 at 12:46 PM nunopicado, Uma boa explicação para algo que muita gente deixa passar sem querer saber 🙂 Queria apenas focar um aspecto que talvez não tenha ocorrido aos leitores. Quando estamos a trabalhar com funções/procedimentos cujos parâmetros contêm uma grande quantidade de informação, é sempre boa ideia utilizar abordagens pass-by-reference uma vez que a outra opção (pass-by-value) implica literalmente que seja criada uma cópia do parâmetro a ser passado. De resto, gostei de ler. Queria que agora alguém desse o salto e começasse a falar de pointers em Pascal, visto que eu não consegui ainda arranjar o tempo para escrever algo sobre o assunto.
nunopicado Posted October 10, 2011 at 12:50 PM Author Report #415315 Posted October 10, 2011 at 12:50 PM É verdade Pedro, a passagem por referência acaba por consumir menos recursos por não haver cópia de valores. Quanto aos ponteiros, vou deixar essa para ti! 🙂 Há anos que não lhes mexo, e mesmo na altura nunca dei grande uso, pelo que é melhor deixar a explicação para alguém que esteja mais à vontade com eles! Abraço e obrigado "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
passarito Posted October 10, 2011 at 01:14 PM Report #415317 Posted October 10, 2011 at 01:14 PM Os ponteiros é algo de de maravilhoso para quem necessita de velocidade no tratamento de registos. Apenas para dar um exemplo, tinha programas de clientes e fornecedores, assentes em base de dados de registos de Pascal (vulgos records). Estes programas tinha diversas listagens. As mais morosas eram as que eram ordenadas por um campo qualquer... ou nome, ou código postal, ou mesmo dois campos em simultâneo tipo data e nome. Enfim, quem penso que estão a ver o objectivo. Ora estas listagens ordenadas demoravam na ordem das 2 a 3 horas tanto que eu aconselhava às pessoas a executá-las à hora de almoço. Após a alteração dos programas e reprogramação com ponteiros as listagens passaram a demorar 2 a 3 minutos. E não, não estão a exagerar!!! :smoke: Quem trabalha com file records, deve de apreender o conceito com mais facilidade, mas não é facil! :fartnew2:
pwseo Posted October 10, 2011 at 01:31 PM Report #415319 Posted October 10, 2011 at 01:31 PM A questão dos pointers é que eles são essenciais para qualquer tipo de estrutura de dados que não seja uma array de um tipo de dados simples. Uma vez que a base de qualquer programa eficiente assenta na escolha e implementação correcta de algoritmos que operem sobre estruturas de dados eficientes, e sabendo que os pointers são invariavelmente utilizados em tais estruturas de dados, é absolutamente essencial a sua compreensão e utilização para o desenvolvimento de programas com futuro. Em C, as pessoas aprendem a usá-los porque sem eles de facto não fazem nada. Mas em Pascal há muita resistência ao conceito porque a linguagem facilita a sua não-utilização (e é necessário contrariar esta tendência), o que é absurdo, visto que a própria sintaxe para pointers é muito mais confortável que aquela vista em C.
thoga31 Posted October 10, 2011 at 02:51 PM Report #415328 Posted October 10, 2011 at 02:51 PM @pedro, Fico à espera de umas palavrinhas tuas sobre pointers, uma vez que eu não sei nada sobre eles e as tentativas que já fiz para entrar nessa área foram infrutíferas. Aliás, é o grande "buraco" do meu Tutorial, diga-se. 🙂 Precisamos de informação de confiança, mas leve e concisa. Estou farto de explicações extra-longas de nada. Força nisso quando tiveres tempo! 😛 Knowledge is free!
pwseo Posted October 10, 2011 at 03:19 PM Report #415335 Posted October 10, 2011 at 03:19 PM Tenho o texto começado, mas como tu dizes, é necessário que seja algo leve e conciso. Eventualmente será terminado e publicado, claro, mas seria bom se alguém com mais paciência e disponibilidade se aventurasse também (até porque isso facilitaria a análise crítica do tema) 🙂
passarito Posted October 10, 2011 at 09:54 PM Report #415411 Posted October 10, 2011 at 09:54 PM Vou tentar qualquer coisa nesse sentido....
diago2011 Posted November 11, 2011 at 04:29 AM Report #420162 Posted November 11, 2011 at 04:29 AM grande explicaçao, a pessoas assim a que se lhe dar o seus valor Os meus sinceros Parabens 😛
nunopicado Posted November 11, 2011 at 08:32 AM Author Report #420166 Posted November 11, 2011 at 08:32 AM grande explicaçao, a pessoas assim a que se lhe dar o seus valor Os meus sinceros Parabens 😉 B) Obrigado... 😛 "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
thoga31 Posted November 13, 2011 at 07:17 PM Report #420492 Posted November 13, 2011 at 07:17 PM Disponível na Wiki: https://wiki.portugal-a-programar.pt/dev_geral/pascal/passagem_parametro_referencia/ 😉 Knowledge is free!
Guest GuiGa Posted January 16, 2013 at 01:09 PM Report #491431 Posted January 16, 2013 at 01:09 PM Puxa vida. Eu não sabia disso. Muito obrigado nunopicado. Não sabia que o uso da palavra chave var no escopo criava este tipo de efeito. Genial. Isso substitui ponteiros. :-)
thoga31 Posted January 16, 2013 at 09:35 PM Report #491492 Posted January 16, 2013 at 09:35 PM Puxa vida. Eu não sabia disso. Muito obrigado nunopicado. Não sabia que o uso da palavra chave var no escopo criava este tipo de efeito. Genial. Isso substitui ponteiros. :-) Na realidade, é o que se pode chamar de syntactic sugar que o Pascal te oferece para evitares criar ponteiros para este fim de forma explícita. Eles são utilizados à mesma, nós é que não o "vemos" directamente no código. Torna-se mais agradável utilizar a keyword var. 🙂 Knowledge is free!
pwseo Posted January 16, 2013 at 10:04 PM Report #491496 Posted January 16, 2013 at 10:04 PM Genial. Isso substitui ponteiros. :-) Na realidade, a keyword var substitui os apontadores para este caso específico da passagem de parâmetros. Noutros casos a sua utilização não é contornável, como por exemplo a implementar certas estruturas de dados, ou certos algoritmos 🙂
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now