2. Instituto de Computação – UFAL
Exercício em sala
Objetivo: ler 03 numeros nas variaveis x,y e z e
depois ordenar x,y e z de tal forma que x
armazene o menor valor, y o intermediário e z o
maior
rodrigo@ic.ufal.br
3. Instituto de Computação – UFAL
Código repetido
O que queremos com
esses 03 trechos?
Trocar os valores de duas
variáveis, correto?
Ou seja, queriamos
isolar uma
funcionalidade
Uma função de trocar
valores
rodrigo@ic.ufal.br
4. Instituto de Computação – UFAL
Não seria melhor assim?
Ok … vamos tentar
rodrigo@ic.ufal.br
trocar(x,y)
trocar(x,z)
trocar(y,z)
6. Instituto de Computação – UFAL
Os valores foram trocados?
Não, né?
Passagem por valor
A passagem de parâmetro foi feita por valor
É feita uma cópia do valor da variável
rodrigo@ic.ufal.br
8. Instituto de Computação – UFAL
Ponteiros
Ao declarar uma variável sempre informamos o
tipo dela
int a;
float soma;
…
Lembra da 1a aula?
As variáveis ficam na memória
Endereço e Conteúdo
rodrigo@ic.ufal.br
9. Instituto de Computação – UFAL
Variáveis
Já sabemos alterar o
conteúdo das
variáveis
Comando de
atribuição
resto = 25;
soma =soma + i;
…
Mas como descobrir o
endereço de memória
das nossas variáveis?
rodrigo@ic.ufal.br
En
d.
Conteúdo
1 34
2 “O rato roeu a roupa do rei de
roma”
3 34.67
4 1
5 0
6 “aula de p1”
7 4677
… 123
n
10. Instituto de Computação – UFAL
Operador &
Este operador nos fornece o endereço de
memória de uma variável
Exemplo:
main()
{
int a = 1;
printf("O endereco de a eh: %pn",&a);
}
rodrigo@ic.ufal.br
11. Instituto de Computação – UFAL
Um novo tipo de variável: ponteiro
O tipo da variável define os valores válidos para
uma variável
Exemplo
int: valores inteiros
char: caracteres
float: ponto flutuante
…
Um ponteiro é um tipo de variável cujos valores
válidos são endereços de memória
rodrigo@ic.ufal.br
12. Instituto de Computação – UFAL
Como funciona?
Imagine uma caixa postal
Caixa postal 22300
A caixa postal é só um endereço
Ela aponta para uma localização que contém
um imóvel (conteúdo)
Os imóveis podem ser de vários tipos
Residencial casa, residencial apartamento, comercial
…
Ou seja, a caixa postal contém um endereço
para um conteúdo de um determinado tipo
A caixa postal é um ponteiro
rodrigo@ic.ufal.br
13. Instituto de Computação – UFAL
… voltando ao C
Um ponteiro é um endereço para um
determinado tipo
int
float
char
outro ponteiro
…
rodrigo@ic.ufal.br
14. Instituto de Computação – UFAL
Ponteiros
Endereço Identificador Conteúdo
0xFF4454 a 5
… … …
… … …
… … …
… … …
0xBBA031 b 12
rodrigo@ic.ufal.br
ponteiro_a
15. Instituto de Computação – UFAL
Declaração de ponteiros
main()
{
int a = 1;
int b = 2;
int *pt_a;
…
rodrigo@ic.ufal.br
16. Instituto de Computação – UFAL
Atribuição com ponteiro
main()
{
int a = 1;
int b = 2;
int *meu_ponteiro;
meu_ponteiro = &a; // atribui o endereço de a
…
rodrigo@ic.ufal.br
17. Instituto de Computação – UFAL
Acesso ao conteúdo do local apontado pelo
ponteiro: *, o operador de “dereference”
main()
{
int a = 1;
int b = 2;
int *pt_a;
pt_a = &a;
*pt_a = 50; // o que vai acontecer aqui?
…
rodrigo@ic.ufal.br
19. Instituto de Computação – UFAL
Interessante né? mas e daí?
Vamos voltar para a nossa função de troca
rodrigo@ic.ufal.br
E se …
•na nossa função recebessemos os
endereços das variáveis que desejamos
trocar
•Com o endereço, poderíamos trocar os
valores
20. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 5
0xFF1242 y 3
0xBBA031 z 2
0xABA005 aux ---
a
b
void trocar_valores(float *a, float *b)
{
float aux;
21. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 5
0xFF1242 y 3
0xBBA031 z 2
0xABA005 aux 5
a
b
void trocar_valores(float *a, float *b)
{
float aux;
aux = *a;
22. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 5
0xFF1242 y 3
0xBBA031 z 2
0xABA005 aux 5
a
b
void trocar_valores(float *a, float *b)
{
float aux;
aux = *a;
*a = *b;
23. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 3
0xFF1242 y 3
0xBBA031 z 2
0xABA005 aux 5
a
b
void trocar_valores(float *a, float *b)
{
float aux;
aux = *a;
*a = *b;
24. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 3
0xFF1242 y 3
0xBBA031 z 2
0xABA005 aux 5
a
b
void trocar_valores(float *a, float *b)
{
float aux;
aux = *a;
*a = *b;
*b = aux;
}
25. Instituto de Computação – UFAL
Ideia
trocar_valores(&x,&y)
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 3
0xFF1242 y 5
0xBBA031 z 2
0xABA005 aux 5
a
b
void trocar_valores(float *a, float *b)
{
float aux;
aux = *a;
*a = *b;
*b = aux;
}
26. Instituto de Computação – UFAL
Ideia
Ao sair … do escopo local as variáveis são
eliminadas
rodrigo@ic.ufal.br
Endereço Identificador Conteúdo
0xFF4454 x 3
0xFF1242 y 5
0xBBA031 z 2if (y < z) // neste caso y é o menor
{
// troca os conteúdos de x e de y
trocar_valores(&x,&y);
}
else // neste caso z é o menor
27. Instituto de Computação – UFAL
O programa completo
funcao_trocar_valores3.c
rodrigo@ic.ufal.br
28. Instituto de Computação – UFAL
Passagem por referência
O que acabamos de fazer foi passar os
parâmetros por referência ao invés de passar
por valor
Passamos apenas uma referência para a variável
externa
O seu valor não é copiado
Mais eficiente
Exige cuidados com efeitos colaterais
rodrigo@ic.ufal.br
29. Instituto de Computação – UFAL
Algumas reflexões
Pra que ponteiros?
C é de uma época em que os computadores eram
menos poderosos
Necessidade de uso eficiente de processamento e
memória
Logo, habilidade de trabalhar diretamente a memória
é muito útil
E por que ainda usamos ponteiros?
Necessidade de eficiência ainda é importante
rodrigo@ic.ufal.br
30. Instituto de Computação – UFAL
Exemplos
main()
{
int x = 7 ;
int *px ;
px = &x ;
*px = 8 ;
printf( "%dn" , x ) ;
printf( "%dn" , &x ) ;
printf( "%dn" , px ) ;
printf( "%dn" , *px ) ;
}
rodrigo@ic.ufal.br
31. Instituto de Computação – UFAL
Exemplos
void exemplo2()
{
int firstvalue, secondvalue;
int * mypointer;
mypointer = &firstvalue;
*mypointer = 10;
mypointer = &secondvalue;
*mypointer = 20;
printf("%dn",firstvalue);
printf("%dn",secondvalue);
}
rodrigo@ic.ufal.br
33. Instituto de Computação – UFAL
Exemplos
Assuma que os seguintes endereços:
c é 1
d é 2
e é 3
Qual a saída do programa abaixo:
char c = 'T', d = 'S';
char *p1 = &c;
char *p2 = &d;
char *p3;
p3 = &d;
printf("%cn",*p3);
p3 = p1;
printf("%c %pn", *p3, p3);
*p1 = *p2;
printf("%c %pn", *p1, p1 );
rodrigo@ic.ufal.br
34. Instituto de Computação – UFAL
Exemplos
int *p;
int i;
int k;
i = 42;
k = i;
p = &i;
Qual dos seguintes comandos muda o valor de i para
75?
k = 75;
*k = 75;
p = 75;
*p = 75;
rodrigo@ic.ufal.br
35. Instituto de Computação – UFAL
Qual o valor de y?
int main()
{
int y, *p, x;
y = 0;
p = &y;
x = *p;
x = 4;
(*p)++;
x;
(*p) += x;
printf ("y = %dn", y);
return(0);
}
Rodrigo Paes – r0drigopaes@yahoo.com.br
36. Instituto de Computação – UFAL
Exercício: escreva a função ordenar
int main()
{
int a, b, c, d, e;
printf("Digite 05 numerosn");
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
ordenar(&a,&b,&c,&d,&e);
printf("Os numeros ordenados em ordem decrescente sao:
%d, %d, %d, %d, %dn",a,b,c,d,e);
return 0;
}
Rodrigo Paes – r0drigopaes@yahoo.com.br
38. Instituto de Computação – UFAL
Lembra como você usa os arrays?
…
int array[9];
array[0] = 20;
printf(“%d”, array[0] );
…
rodrigo@ic.ufal.br
39. Instituto de Computação – UFAL
Por debaixo dos panos
Uma variável array é um ponteiro constante
para uma área de memória onde os elementos
serão armazenados
int array[9];
*array = 20;
printf(“%d”, *array );
Perceba que a variável array é um ponteiro para o
primeiro elemento
rodrigo@ic.ufal.br
20
array
40. Instituto de Computação – UFAL
E como acessar os outros elementos?
Aritmética de ponteiros
int array[9];
*array = 20;
*(array +1) = 30;
*(array +2) = 40;
rodrigo@ic.ufal.br
20 30 40
array
32 bits 32 bits 32 bits 32 bits 32 bits 32 bits 32 bits 32 bits 32 bits
Desloca 1 * sizeof(int) bytes
Desloca 2 * sizeof(int) bytes
41. Instituto de Computação – UFAL
Então …
array[7]=96;
É idêntico a fazer:
*(array+7)=96;
Podemos também:
int *p;
int array[5];
p = array;
p = &array[4];
p[-1] = 5;
printf("%dn",array[3]);
*(p-1) = 8;
printf("%dn",array[3]);
rodrigo@ic.ufal.br
42. Instituto de Computação – UFAL
Atenção
int *p;
p[3] = 8;
Certo ou errado?
rodrigo@ic.ufal.br
43. Instituto de Computação – UFAL
Quiz: pode ou não ? Qual a saída?
#include <stdio.h>
int main()
{
int a[10];
*a = 3;
a[1]= 4;
printf("%dn%dn",a[0],a[1]);
}
rodrigo@ic.ufal.br
44. Instituto de Computação – UFAL
Quiz: pode ou não? Qual a saída?
int main()
{
int a[10];
*a = 3;
a[1]= 4;
a++;
*a =5;
printf("%dn%dn",a[0],a[1]);
}
rodrigo@ic.ufal.br
Não podemos alterar o ponteiro
45. Instituto de Computação – UFAL
Passando arrays para funções
void funcao(int *a, int tamanho)
{
int i;
for (i=0; i< tamanho ; i++)
{
a[i] = i*i;
}
}
main()
{
int x[5];
funcao(x,5);
}
rodrigo@ic.ufal.br
46. Instituto de Computação – UFAL
Ponteiros para ponteiros
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
printf("%cn",a);
printf("%cn",*b);
printf("%cn",**c);
rodrigo@ic.ufal.br
47. Instituto de Computação – UFAL
Arrays bidimensionais :: estáticos
int array1[2][2] = {{0, 1}, {2, 3}};
…
Na memória:
0 1 2 3
O mesmo layout de:
int array2[4] = { 0, 1, 2, 3 };
rodrigo@ic.ufal.br
48. Instituto de Computação – UFAL
Arrays bidimensionais :: estáticos
Um array 2D não é a mesma coisa que int**
Array para ponteiros, só “funciona”
automaticamente no primeiro nível
Logo:
int array1[2][2] = {{0, 1}, {2, 3}};
void function2(int a[][2]); ou:
void function2(int a[2][2]);
Diferente para alocação dinâmica
rodrigo@ic.ufal.br
49. Instituto de Computação – UFAL
Alocação dinâmica
Muitas vezes só sabemos o tamanho do nosso
array durante a execução do programa
Usar esta abordagem permite protelar a decisão
sobre o tamanho do bloco de memória
necessário para armazenar um array
Quando aquela memória não é mais necessária,
ela pode ser liberada para outros usos
rodrigo@ic.ufal.br
50. Instituto de Computação – UFAL
Alocação dinâmica
Exemplo. Alocação de um array com 10 inteiros
int *iptr;
iptr = (int *)malloc(10 * sizeof(int));
if (iptr == NULL)
{
... Rotina de erro vem aqui ...
}
rodrigo@ic.ufal.br
51. Instituto de Computação – UFAL
Alocação dinâmica e arrays
int *iptr;
iptr = (int *)malloc(10 * sizeof(int));
if (iptr == NULL)
{
... Rotina de erro vem aqui ...
}
int k;
for (k = 0; k < 10; k++)
iptr[k] = 2;
rodrigo@ic.ufal.br
52. Instituto de Computação – UFAL
Alocar uma matriz de inteiros
int **mi;
int row,col;
mi = malloc (ROWS * sizeof (int *));
for (row = 0; row < ROWS; row++)
{
mi[row] = malloc (COLS * sizeof (int));
}
for (row = 0; row < ROWS; row++)
{
for (col = 0; col < COLS; col++)
{
mi[row][col] = 17;
}
}
rodrigo@ic.ufal.br
53. Instituto de Computação – UFAL
Alocar uma matriz de inteiros ::
continuamente
https://dl.dropbox.com/u/17364381/p1/alocacao
_continua_matriz.c
rodrigo@ic.ufal.br
54. Instituto de Computação – UFAL
Realocação
https://dl.dropbox.com/u/17364381/p1/realloc.c
rodrigo@ic.ufal.br
55. Instituto de Computação – UFAL
Liberar a memória
/* free example */
#include <stdlib.h> /* malloc, calloc, realloc, free */
int main ()
{
int * buffer1, * buffer2, * buffer3;
buffer1 = (int*) malloc (100*sizeof(int));
buffer2 = (int*) calloc (100,sizeof(int));
buffer3 = (int*) realloc (buffer2,500*sizeof(int));
free (buffer1);
free (buffer3);
return 0;
}
rodrigo@ic.ufal.br