65
Ponteiros prof. Fabrício Olivetti de França

Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Embed Size (px)

Citation preview

Page 1: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteirosprof. Fabrício Olivetti de França

Page 2: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Anteriormente em prog. estrut.

Vimos que as variáveis representando arrays em C armazenam apenas um apontador para o endereço de memória contendo os valores da array.

2

Page 3: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Anteriormente em prog. estrut.

Uma das características desses apontadores é que, ao passar uma array como parâmetro de uma função, o seu conteúdo era alterado dentro dela.

3

Page 4: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaUm computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte.

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

9 bytes

4

Page 5: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaPara o computador um byte da memória pode representar um tipo char ou uma sequência de dois bytes um int.

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

9 bytes

5

Page 6: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaA diferença entre os tipos na linguagem C é apenas quantos bytes consecutivos de memória serão utilizados.

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

9 bytes

6

Page 7: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaÉ por isso que na linguagem C podemos realizar operações entre diferentes tipos:

int x = 3;char c = ‘A’;x+c /* == ‘D’ */

7

Page 8: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaE transformar um tipo em outro através do chamado casting.

int x = 65;printf(“%c”, (char) x); /* ‘A’ */

8

Page 9: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaO casting de variáveis indica para o programa que tal variável deve ser tratada como outro tipo naquela instrução específica:

tipo1 variavel;(tipo2) variavel; ← casting!!

9

Page 10: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Relembrando sobre MemóriaO operador unário & permite obter o endereço da memória que certa variável reside:

int x = 10;printf(“A variável x está na posição %p da memória\n”, &x );

10

Page 11: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteiros

A linguagem C permite criar apontadores, denominados ponteiros para quaisquer tipos de variáveis.

Os ponteiros são variáveis de 2 ou 4 bytes (dependendo do computador) que armazenam um endereço de memória.

11

Page 12: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

PonteirosPara declarar um ponteiro basta usar * após a declaração do tipo:

/* ponteiro para uma variável contendo um inteiro */int * x;

12

Page 13: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

PonteirosNote que, ao contrário da declaração de tipo, nesse caso a variável pode apenas receber endereço de memória.

int * x;x = 100;printf(“%d\n”, *x); ← conteúdo do endereço “100” da memória

<na verdade esse programa "trava">13

Page 14: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteiros

int x;int * y;x = 10;y = &x;

14

Page 15: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteirosint x;int * y;x = 10;

0001 0001

0010 0010

0000 0000

0000 1010

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

xy

15

Page 16: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteirosint x;int * y;x = 10;

11 27 0 10

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

xy

16

Page 17: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Ponteirosy = &x;

11 27 0 10

0x11

200x

1121

0x11

220x

1123

0x11

240x

1125

0x11

260x

1127

0x11

280x

1129

xy

17

Page 18: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

PonteirosPara acessar o conteúdo do endereço que um ponteiro aponta, utilizamos o operador *:

printf(“%d\n”, *y); /* conteúdo de x → 10 */

18

Page 19: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

PonteirosOs operadores aritméticos são válidos para as variáveis ponteiros:

int x = 10;int * y = &x;*y = *y + 10; /* x agora é 20 */y = y + 1; /* avança sizeof(int) bytes na memória */

19

Page 20: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exemplo void troca (int x, int y) { int temp; temp = x; x = y; y = temp; }

20

Page 21: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exemplo

A função recebe uma cópia do valor das variáveis, então ao fazer:

troca(a, b);

As variáveis a e b não terão seus valores trocados.

21

Page 22: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Passando ponteiros como parâmetrosSe ao invés de passar uma cópia dos valores, passassemos uma cópia dos endereços de memória, poderíamos alterar o conteúdo:

troca(&a, &b);

22

Page 23: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Passando ponteiros como parâmetros void troca (int * px, int * py) { int temp; temp = *px; *px = *py; *py = temp; }

23

Page 24: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Passando ponteiros como parâmetrostroca(&a, &b);

adaptado do livro de Kernighan & Ritchie

a

b

px

py

Função troca():

24

Page 25: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Inicializando ponteirosNa biblioteca stdlib.h define-se a constante NULL representando o valor nulo para ponteiros:

#include <stdlib.h>int * x = NULL; /* não aponta o dedo pra ninguém */

25

Page 26: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

ExercícioFaça uma função quociente_resto() que recebe dois inteiros x e y e dois ponteiros para inteiros q e r para armazenar o quociente q e o resto r.

Faça com que a função retorne 1 em caso de sucesso e 0 em caso de erro (que erro ela pode ter?)

26

Page 27: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

Quanto de memória essa função utiliza?

Quantas instruções ela executa?

27

Page 28: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Vetores como ponteirosVimos anteriormente que uma array:

int x[100];

Reserva 100*sizeof(int) posições de memória e inicializa a variável x com o endereço da primeira posição.

28

Page 29: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Vetores como ponteirosDessa forma:

x contém o endereço da memória do primeiro elemento.(*x) é o conteúdo do primeiro elemento da array*(x+3) é o conteúdo da posição 3 da array

29

Page 30: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Vetores como ponteirosUma forma alternativa de declarar funções que recebem arrays:

int soma (int * v, int n);

30

Page 31: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Vetores como ponteirosint soma (int *v, int n){ int i, total = 0; for (i=0; i<n; i++) { total += v[i]; } return total;}

31

Page 32: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Vetores como ponteiros

int x[100];…soma(x, 100); /* soma todos os elementos de x */soma(x+5, 50); /* soma os 50 primeiro elementos de x a partir da posição 5 */

32

Page 33: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

MallocA linguagem C permite que façamos a função de alocar memória dinamicamente para criar arrays.

Para isso utilizaremos a instrução malloc.

(void *) malloc( size_t size );

33

Page 34: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Malloc

size_t - dependente da plataforma, variável para indicar tamanho em bytes.

void * - ponteiro do tipo void é utilizado para referenciar um tipo genérico, que pode ser transformado em qualquer outro tipo.

34

Page 35: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Malloc#include <stdlib.h>#include <stdio.h>void main ( ){ int * v; int tamanho; printf(“Entre com o tamanho: “); scanf(“%d”, &tamanho); v = malloc( tamanho * sizeof(int) );} 35

Page 36: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Malloc

v = malloc( tamanho * sizeof(int) );

tamanho * sizeof(int) - calcula quantos bytes tem um array com tamanho elementos do tipo int.

36

Page 37: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Malloc

Nota1: uma vez alocado o espaço, não existe garantias do valor inicial dos elementos da array!!

Nota2: a função malloc não assegura que o espaço de memória foi realmente alocado, por isso é importante verificar se o ponteiro é diferente de NULL antes usá-lo!

37

Page 38: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Malloc

v = malloc( tamanho * sizeof(int) ); printf(“%d\n”, v[0]); /* indeterminado */ v[0] = 10; printf(“%d\n”, v[0]); /* 10 */

38

Page 39: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

FreeApós o uso da array e antes de terminar o programa, devemos liberar a memória para que ela seja utilizada por outros processos ou programas.

free(v);

39

Page 40: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Array Dinâmica

int ** array;

Ela na verdade é uma array contendo arrays. Cada linha pode ter um número diferente de colunas.

Page 41: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Array Dinâmica

int ** array = malloc(sizeof(int *)*N);for (i=0;i<N;i++) { array[i] = malloc(sizeof(int)*M);

O segmento de memória não é contínuo, cada linha aponta para um segmento diferente.

Page 42: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Array Dinâmica

for (i=0;i<N;i++) { free(array[i]);free(array);

Da mesma forma devemos liberar o espaço de cada elemento da array bidimensional.

Page 43: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Array DinâmicaNesse caso não podemos fazer *( &(array[0][0]) + i*M + j ) para acessar um elemento utilizando aritmética de ponteiros.

Devemos fazer:

*(*(array + i) + j)

Page 44: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Array DinâmicaA declaração de uma função que recebe uma array dinâmica como parâmetro é

funcao( int ** array );

Page 45: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

void half_double (int * x, int * y){ x /= 2; y *= 2;}

45

Page 46: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

int m = 10;int n = 20;half_double(m,n);printf(“%d %d\n”, m, n);

46

Page 47: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

1) O que a função irá imprimir?

2) Ela faz o que é esperado?

3) Como você arrumaria o erro?

47

Page 48: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

int * x;char * y;…

As operações x+1 e y+1 somam o mesmo valor (1) ao endereço apontado por x e y?

48

Page 49: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

Faça uma função chamada copy que recebe dois ponteiros int: from e to e um int chamado n.

A função deve copiar os primeiros n elementos de from para to.

49

Page 50: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

O que devo alterar na função para que ela funcione com todos os tipos de variáveis?

O significado da variável n muda?

50

Page 51: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

O seu chefe ouviu dizer que o laço for é muito mais custoso que o laço while. Reimplemente a função utilizando while.

51

Page 52: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercício

Usar como condição de parada quando a variável chega em zero é mais rápido!

52

Page 53: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

ExercícioEu quero que a função tenha apenas uma linha de instrução! (quanto menor o código mais rápido ele deve ficar né?)

53

Page 54: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Exercíciovoid copy (void * from, void * to, size_t n){ while(n--) *to++ = *from++;}

54

Page 55: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Curiosidade

55

Page 56: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Dado uma variável do tipo float com valor entre [1,2], temos que:

https://en.wikipedia.org/wiki/File:Float_w_significand_2.svg

E M

56

Page 57: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Desconsiderando o sinal, o número em ponto flutuante é representado por:

x = 2E-127 (1 + M.2-23)

57

Page 58: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Logo:

log2(x) = (E-127) + log2(1 + M.2-23)

58

Page 59: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Temos que:

0 <= M.2-23 < 1

59

Page 60: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)E nessa situação temos que:

log2(1 + M.2-23) ~ M.2-23 + eps

60

Page 61: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Logo:

log2(x) = (E-127) + M.2-23 + eps

61

Page 62: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)Se convertermos x para int os 32 bits representarão:

(int) x = E.223 + M

62

Page 63: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)(int) x = E.223 + M = 223 (E + M.2-23 ) = 223 (E -127 + 127 + M.2-23 + eps - eps) = 223 (E - 127 + M.2-23 + eps + 127 - eps)

63

Page 64: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)(int) x = E.223 + M = 223 (E - 127 + M.2-23 + eps + 127 - eps) = 223 (log(x) + 127 - eps) = 223 log(x) + 223(127 - eps)

64

Page 65: Ponteiros - Fabrício Olivetti de França · Um computador possui um vetor de posições de memória devidamente endereçadas. Cada elemento da memória armazena um byte. 0x1120 0x1121

Calculando log2(x)float x = …;long ix = * ( long * ) &x;log(x) = ( (float) ix )/8388608.0 - 127 + 0.0430357;

eps ótimo = 0.0430357

(historicamente foi encontrado por tentativa e erro)

65