Você está na página 1de 31

AULA PASSADA

•  Funções void: não retornam valor associado à função


1.  sem parâmetros (parâmetros void)
2.  com parâmetros:
1.  passados por valor
2.  passados por referência
•  Funções tipadas ou com retorno: devolvem um único
valor associado a execução da função, usando o comando
return.
1.  sem parâmetros (parâmetros void)
2.  com parâmetros.

1 INF 01202 - Prof. Marcelo Walter – Aula 18


Exercício com função tipada:

Calcule o valor de ex usando a série abaixo:


0 1 2
xx x x
e = + + + …,
0! 1! 2!
onde x é um valor real, lido do teclado. Os termos
devem ser inseridos enquanto forem maiores do que
0,0001 (em valor absoluto)

Funções envolvidas:

• float potencia (float x, int n ) (a função pow pode


ser usada, mas a ideia é criar uma alternativa)
• float fatorial (int n) (já feita no exemplo anterior)
• float EnaX (float x)
2 INF 01202 - Prof. Marcelo Walter – Aula 18
Solução (resta criar o main)
float potencia (float x, int n)
// Calcula o valor de x elevado na potencia
// n (assume n inteiro nao negativo)
{
float p; float EnaX (float x)
int i; {
p = 1; // Calcula o valor aproximado de exp(x) com base na
if (n > 0) serie de potencias truncada
for (i=0;i<n;i++) int i = 0;
p = p*x; float total = 0;
return p; float parcela = 1; // inicializa com parcela inicial
} while (fabs(parcela) > 0.0001) //requer a lib math.h
//para o comando fabs
{
Cuidado! Dependendo
total = total + parcela;
do valor de X,
rapidamente o i++;
fatorial cresce para parcela = potencia(x,i) / fatorial(i); // calcula a
atingir a precisão // proxima parcela
necessária e fica }
fora do intervalo return total;
para int. }
3 INF 01202 - Prof. Marcelo Walter – Aula 18
Aula de Hoje
Formas de passagem de valores de parâmetros

•  Por valor:
–  visto na aula passada
–  passa somente um valor.
–  para cada parâmetro, é alocada uma área
de uso local da função e o valor do
argumento é copiado para esta área (valor
inicial).
–  alterações deste valor, durante o
processamento da função, não alteram o
valor da variável enviada pelo programa que
chamou a função (argumento ou parâmetro
real), apenas a cópia local.

4 INF 01202 - Prof. Marcelo Walter – Aula 18


Exemplo: função que calcula média aritmética de 3
números float e retorna o resultado

float calcula_media(float a, float b, float c)


{
float m;
int main ( )
m = (a+b+c)/3; {
a = 2*a; float a=3.2, b=4.5, c=7.8, media;
b = 3*b;
c = 4*c; printf(“a = %3.2f b= %3.2f c = %3.2f\n”, a,b,c);
media = calcula_media(a,b,c);
return m; printf(“A media vale %3.2f\n”, media);
} printf(“a = %3.2f b= %3.2f c = %3.2f\n”, a,b,c)
return 0;
}

Os valores não mudam


após a execução da
função!!
5 INF 01202 - Prof. Marcelo Walter – Aula 18
Passagem por valor resolve esse enunciado?

•  Fazer uma função que receba 2 inteiros x e y e troque seus valores.

void troca(int x, int y) int main()


{ {
int temp;
temp = x; int a=5, b=10;
x = y; printf("a=%d b=%d\n",a,b);
y = temp; troca(a,b);
printf(“\n*** Na funcao:”); printf("a=%d b=%d\n",a,b);
printf(”x=%d y=%d\n",x,y); .....
} }

O que será impresso na tela?

6 INF 01202 - Prof. Marcelo Walter – Aula 18


•  Os valores de a e b não foram trocados, porque a passagem de
parâmetros foi feita por valor.
•  Passagem de parâmetro por valor:
–  Variável local x é inicializada com conteúdo de a (argumento);
–  Variável local y é inicializada com conteúdo de b (argumento);
–  Dentro do subprograma, os valores de x e y são trocados, mas
esta mudança é feita sobre as cópias locais dos valores e não é
propagada para fora do subprograma e a e b permanecem com
os valores originais.

7 INF 01202 - Prof. Marcelo Walter – Aula 18


Tipos de funções:

•  Funções void*: não retornam valor associado à função


1.  sem parâmetros (parâmetros void*)
2.  com parâmetros:
1.  passados por valor
2.  passados por referência (endereço)
•  Funções tipadas ou com retorno: devolvem um único
valor associado a execução da função, usando o comando
return.
1.  sem parâmetros (parâmetros void*)
2.  com parâmetros.
1.  passador por valor
2.  passados por referência (endereço)

8 INF 01202 - Prof. Marcelo Walter – Aula 18


Formas de passagem de valores de parâmetros

•  Por referência:
–  passa um endereço de memória, o qual é associado ao parâmetro,
localmente.
–  alterações feitas no parâmetro afetam o conteúdo do endereço
referida na chamada (argumento ou parâmetro real).
–  para passar parâmetros por referência precisamos usar
ponteiros.

9 INF 01202 - Prof. Marcelo Walter – Aula 18


Rua
Nascimento
Silva, 107

Rua Nascimento Silva, 107

A ideia de ponteiros

10 INF 01202 - Prof. Marcelo Walter – Aula 18
Ponteiros

•  Mecanismo para referenciar algo indiretamente

•  Diferenciar entre o endereço de um assento no


show e a pessoa que está sentada no assento
específico

Maria está sentada no


assento 50 da fila 118

Código do local: a50f118


11 INF 01202 - Prof. Marcelo Walter – Aula 18
Variáveis e endereços

Toda e qualquer variável utilizada por um programa reside em determinado


endereço de memória.
O acesso ao endereço de uma variável pode ser feito simbolicamente através de
seu nome. Essa referência é simbólica porque o endereço de memória propriamente
dito NÃO é especificado (na verdade não há necessidade de sabermos...)
Endereço de Memória
A declaração: Variável Valor da Variável (arbitrário)
int x;
produz x ? AFA1
Endereço de Memória
O comando: Variável Valor da Variável
(arbitrário)
x = 3;
produz x 3 AFA1

AFA1 = 1010 1111 1010 0001 = 44961

12 INF 01202 - Prof. Marcelo Walter – Aula 18


O que são ponteiros?

•  Ponteiros são variáveis que guardam endereços de memória.

A posição de memória 1000 armazena o endereço de


memória 1003, cujo conteúdo é o caracter D.

O endereço é a posição de uma outra variável na memória


Se uma variável a armazena o endereço de uma variável b,
dizemos que a aponta para b!

13 INF 01202 - Prof. Marcelo Walter – Aula 18


Declaração de Ponteiros
  Sintaxe:
  tipo *nome_da_variavel_ponteiro;

asterisco indica que a variável


armazena um endereço de memória,
cujo conteúdo é do tipo especificado.

qualquer tipo válido em C

Exemplos:
float *f; // f é um ponteiro para variáveis do tipo float
int *p; // p é um ponteiro para variáveis do tipo inteiro
char a, b, *p, c, *q; // pode declarar junto com variáveis de mesmo tipo

O asterisco é o mesmo da operação de multiplicação, mas não


provoca confusão porque seu significado depende do contexto em
que é usado!

14 INF 01202 - Prof. Marcelo Walter – Aula 18


Por que os ponteiros têm que possuir um tipo?
Tipos de Dados:
ü  Diferentes tipos de dados necessitam de um número
diferente de bytes de memória para armazenar seu conteúdo.
ü  A declaração do tipo de dado indica o número de bytes
reservados para conteúdos: Depende da
char a = ‘Z’; //1 byte arquitetura !
int n = 1234; //4 bytes Para saber:
float PI = 3.1415; //4 bytes sizeof(tipo)

M a n PI
E 3.1415
Ó Z 1234
R 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 ...
I
A
ü O endereço de uma variável é sempre o MENOR dos endereços,
isto é, o endereço inicial.
ü Um ponteiro para um tipo qualquer indica também sempre o
número de bytes que esse tipo ocupa.

15 INF 01202 - Prof. Marcelo Walter – Aula 18


Operadores de Ponteiros

operador unário, que devolve o endereço de memória de seu


& operando

operador unário que devolve o valor da variável armazenada


* no endereço que o segue

16 INF 01202 - Prof. Marcelo Walter – Aula 18


Voltando ao show do U2

Maria está sentada no assento 50 da fila 118

João está sentado no assento 43 da fila 77

O ingresso no assento 23 da fila 102 não foi vendido

Qual o “conteúdo” de a50f118?

*a50f118 = ? Maria

Onde está sentado Joao?

&Joao= ? a43f77

Qual o “conteúdo” de a23f102?


LIXO! Não podemos garantir o conteúdo
*a23f102= ?
17 INF 01202 - Prof. Marcelo Walter – Aula 18
Exemplo 2: ponteiros e conteudo
#include <stdio.h> count q *m
int main() 60 60 &count
{
int count, q, *m;
m = &count; // recebe endereço de count

count = 60;
q = *m; // recebe conteúdo apontado por m

printf("m = %p\n", m); // %p para imprimir ponteiro (endereço apontado)


printf("q = %d\n", q);
// conteúdo apontado por m
printf(“conteudo do endereco apontado por m: %d\n\n", *m);

return 0;
}

18 INF 01202 - Prof. Marcelo Walter – Aula 18


Atribuições com ponteiros

Como qualquer variável, um ponteiro pode ser usado no lado


direito de um comando de atribuição para passar seu valor
para um outro ponteiro.

Exemplo:
int x = 200, *p1, *p2;
p1 = &x; // p1 aponta para x
p2 = p1; // p2 recebe p1 e também passa a apontar para x
printf("x - %d, p1=%p e p2=%p\n", x, p1, p2); // endereço de x
printf("x - %d, p1=%d e p2=%d\n",x,*p1, *p2); // conteúdo de x

19 INF 01202 - Prof. Marcelo Walter – Aula 18


Exemplo 3 – O que será impresso na tela?

#include <stdio.h>

int main()
{ a x y
int a, *x, *y; 20
10
a = 10;
x = &a;
y = x;
printf("a = %d, *x = %d, *y = %d \n",a,*x, *y);
printf("a = %d, x = %p, y = %p\n\n", a, x, y);
*x = 20;
printf("a = %d, *x = %d, *y = %d \n",a, *x, *y);
printf("a = %d, x = %p, y = %p\n\n", a, x, y);

return 0;
}
20 INF 01202 - Prof. Marcelo Walter – Aula 18
O que será impresso na tela?

#include <stdio.h>

int main()
{
int x=5,*px;

printf("1) x = %d *px = %d px = %p\n", x, *px, px);


px = &x;

printf("2) x = %d *px = %d px = %p\n", x, *px, px);


*px = 10;

printf("3) x = %d *px = %d px = %p\n", x, *px, px);

return 0;
}

21 INF 01202 - Prof. Marcelo Walter – Aula 18


Erro comum 1: Onde está o problema?

#include <stdio.h>

int main()
{
float x;
int *p; Erro de compilação: tipos incompatíveis
p é um ponteiro para inteiros, logo não pode
x = 100; apontar para uma variável do tipo float.
p = &x;
printf("x=%f p=%p\n\n", x,p);
return 0;
}

22 INF 01202 - Prof. Marcelo Walter – Aula 18


Erro comum 2: Onde está o problema?

#include <stdio.h>

int main()
{
int x; Possível erro de execução:
int *p; p não foi inicializado
quando p foi criado, ele aponta para um
x = 100; endereço de memória desconhecido.
*p = x; Resultado imprevisível!!!
printf("x=%d p=%p\n\n", x,p);
return 0;
}

23 INF 01202 - Prof. Marcelo Walter – Aula 18


Sobre a inicialização de ponteiros

•  Ponteiros não devem ser utilizados sem prévia inicialização.


Exemplo correto abaixo:
int x;
float pi = 3.14;
int *ptr_x = &x;
float *ptr_to_pi = &pi;

•  No entanto, podem existir situações* em que não se quer


inicialmente que um ponteiro aponte uma variável. Nesse caso,
deve-se inicializar o ponteiro com NULL. Exemplo:
int a = 5, b = 7;
int *ptr = NULL;

*Estas situações irão aparecer nas próximas disciplinas

24 INF 01202 - Prof. Marcelo Walter – Aula 18


Voltando ao nosso exemplo de troca de valores..

Qual a grande vantagem de


usarmos ponteiros na
passagem de parâmetros?

Modificações feitas nas


variáveis recebidas por
referência, ou seja, usando
ponteiros, alteram o
próprio valor da variável!
25 INF 01202 - Prof. Marcelo Walter – Aula 18
Exemplo 4: passagem por referência
•  Fazer uma função que receba 2 inteiros x e y e troque seus
valores.

void troca(int *x, int *y)


{ // conteúdo dos endereços int main()
int temp; {
int a=5, b=10;
temp=*x; printf("a=%p b=%p\n",&a,&b);
*x = *y; printf("a=%d b=%d\n",a,b);
*y = temp; troca(&a,&b); //aqui, endereços
printf(“\n*** Na funcao\n:”);
printf(”x=%d-y=%d\n", *x,*y); printf("a=%d b=%d\n",a,b);
printf(”x=%p-y=%p\n", x, y);
return 0;
} }
Passagem de parâmetros:
•  x e y agora recebem os endereços de a e b.
•  na função, os valores são buscados e armazenados no
endereço referido, isto é, em a e b!

26 INF 01202 - Prof. Marcelo Walter – Aula 18


•  Os valores foram trocados, pois a passagem de
parâmetros foi feita por referência
•  Observe os mesmos endereços de memória
•  Dentro do subprograma, x e y receberam os endereços
de memória de a e b, e seus conteúdos são alterados

27 INF 01202 - Prof. Marcelo Walter – Aula 18


Exemplo 5

Escreva uma função em C que receba três valores reais


a,b,c, e que retorne as duas raízes x1 e x2 da equação
ax2 + bx + c = 0. Assuma que a equação de segundo grau
possui raízes reais.

Estrutura da função: os parâmetros a,b,c podem ser


passados por valor (pois não serão alterados), mas os
parâmetros x1 e x2 devem ser passados por referência
(pois são, na verdade, parâmetros de saída da função).

void baskara(float a, float b, float c, float* x1, float* x2)


{

}
28 INF 01202 - Prof. Marcelo Walter – Aula 18
Exemplo 5: solução
/*
Exemplo de rotina que acha raizes reais de uma equacao de 2º grau
Entradas: valores a,b,c dos coeficientes
Saidas: valores das raizes x1 e x2
*/

#include<stdio.h>
#include<math.h>

void baskara(float a, float b, float c, float* x1, float* x2)


// funcao baskara. Entradas a,b,c (passagem por valor) e saidas x1, x2 (referencia)
{
float raizdisc;
raizdisc = sqrt(b*b-4*a*c); // raiz do discriminante, evita calculo repetido
*x1 = (-b + raizdisc)/(2*a);
*x2 = (-b - raizdisc)/(2*a);
}

int main() //colocar o main aqui

29 INF 01202 - Prof. Marcelo Walter – Aula 18


Exemplo 5: exemplo de main que chama a função

int main()
{
float a,b,c; //parametros da equacao
float x1,x2; //raizes
puts("Entre os valores de a,b,c:");
scanf("%f%f%f", &a, &b, &c);
baskara(a, b, c, &x1, &x2); //chamada da funcao
printf("As raizes são %.5f e %.5f\n", x1, x2); //impressao das raizes

return 0;
}

30 INF 01202 - Prof. Marcelo Walter – Aula 18


Exemplo 6

•  Escreva um programa com as seguintes funções:

–  a) uma função que receba dois parâmetros inteiros e


troque seus valores (já implementada)

–  b) uma função que receba três inteiros como


argumentos e faça um ajuste tal que, após a
execução, o menor valor esteja no primeiro parâmetro
e o maior no terceiro. Use a função definida na letra
a.

31 INF 01202 - Prof. Marcelo Walter – Aula 18

Você também pode gostar