terça-feira, 15 de dezembro de 2009

Dividir para conquistar! Final (valor x referência)

Encerrando a nossa série sobre modularidade (existem outras coisas a falar, mas elas merecem atenção especial, ou seja, um post só para elas), vamos ver com mais detalhes como as variáveis 'caminham' entre as funções.

Como vimos no post anterior desta série (aqui), as variáveis declaradas entre as {} de uma função são locais à função, ou seja, não são acessíveis por outras funções do programa. No entanto, vimos, aqui, que é possível passar o retorno de uma função, que geralmente é uma variável local da função, para outras funções. Como isso acontece?

Não te conheço, mas sei o que você tem!
A forma correta de chamar uma função é passando os argumentos para os parâmetros que ela utiliza para fazer o seu trabalho. No exemplo que vimos na 1a parte desta série, para somar dois números, na linha 25 passamos as variáveis num1 e num2 como argumentos para a função soma_int que utiliza as variáveis val1 e val2 para fazer o seu trabalho.
Na verdade não passamos as variáveis, e sim o seu conteúdo. O que acontece realmente é que o conteúdo da variável num1 é copiado para a variável val1, e o conteúdo da variável num2 é copiado para a variável val2.
Esta operação é chamada de passagem por valor, porque os valores armazenados nos argumentos são copiados para os parâmetros.
Uma vez que a função trabalha com uma cópia do conteúdo das variáveis num1 e num2, o seu conteúdo permanece intacto, e a função soma_int consegue fazer o seu trabalho corretamente (todos ficam satisfeitos rsrs).
Mas, e se precisarmos alterar o conteúdo das variáveis num1 e num2? Seria possível?
Vejamos isto na prática. Observe o código abaixo.


//TROCANDO O CONTEÚDO DE VARIÁVEIS USANDO FUNÇÕES
#include <stdio.h>
#include <stdlib.h>
 
int ler_int(){
 int num;
 
 printf("Digite um numero inteiro: ");
 scanf("%d", &num);
 return num;
}
 
void troca(int val1, int val2){
 int aux;
 
 aux = val1;
 val1 = val2;
 val2 = aux;
}
 
void exibe_int(int val1, int val2){
 printf("\nO valor de num1 = %d e num2 = %d.\n", val1, val2);
}
 
int main(){
 int num1, num2;
 
 num1 = ler_int();
 num2 = ler_int();
 exibe_int(num1, num2);
 troca(num1, num2);
 exibe_int(num1, num2);
 system("pause");
}


Antes de executar este código, vamos falar sobre a função troca, que aparece na linha 13. Na linha 14, declaramos uma variável aux, que usaremos para salvar o valor armazenado na variável val1 antes de armazenar nela o valor da outra variável, val2, como mostrado nas linhas 16 e 17. O valor salvo em aux, ou seja o valor anterior de val1, será agora armazenado em val2.
Agora que entendemos como funciona a função troca, pode executar o código e observar o resultado.
Acredito que você já sabe o porquê dele não funcionar. Se não sabe, veja a razão.
Quando a função troca é chamada na linha 31, dentro da main, ela recebe os valores das variáveis num1 e num2, que são copiados para as variáveis val1 e val2 que são os seus parâmetros. Na verdade, os valores que são trocados são os de val1 e val2, e não os valores de num1 e num2 como desejado.
Para resolver situações como estas, entra em ação um recurso que já conhecemos: os ponteiros.

Não adianta se esconder... Eu sei onde você mora!
Se você não se recorda do funcionamento de um ponteiro, dê uma olhada aqui.
Agora observe como fica o nosso código usando este recurso.


//TROCANDO O CONTEÚDO DE VARIÁVEIS USANDO FUNÇÕES
#include <stdio.h>
#include <stdlib.h>
 
int ler_int(){
 int num;
 
 printf("Digite um numero inteiro: ");
 scanf("%d", &num);
 return num;
}
 
void troca(int* val1, int* val2){
 int aux;
 
 aux = *val1;
 *val1 = *val2;
 *val2 = aux;
}
 
void exibe_int(int val1, int val2){
 printf("\nO valor de num1 = %d e num2 = %d.\n", val1, val2);
}
 
int main(){
 int num1, num2;
 
 num1 = ler_int();
 num2 = ler_int();
 exibe_int(num1, num2);
 troca(&num1, &num2);
 exibe_int(num1, num2);
 system("pause");
}


Agora funcionou! Você sabe me dizer porquê?
Este uso de ponteiros para tornar possível o acesso a variáveis locais de outras funções é chamado de passagem por referência. Porque na verdade, não se passa o valor da variável, mas a sua referência, ou seja, o seu endereço na memória, que como sabemos, torna possível acessar e alterar esta variável.
Viu como é fácil (os ponteiros são nossos amigos rsrs).
Até a próxima.

Nenhum comentário:

Postar um comentário