prof. ricardo santos [email protected] ponteiros

44
Prof. Ricardo Santos [email protected] PONTEIROS

Upload: internet

Post on 18-Apr-2015

138 views

Category:

Documents


21 download

TRANSCRIPT

Page 1: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Prof. Ricardo [email protected]

PONTEIROS

Page 2: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Ponteiros

Um ponteiro é uma variável que contém um endereço de memória. Este endereço é a posição de outra variável na memória. Se uma variável contém o endereço de uma outra, dizemos que a primeira aponta para a segunda.

Declaração: tipo_base *nome;

Exemplo: int *p;

Onde tipo_base é qualquer tipo válido em C e nome é o nome da variável ponteiro. O tipo_base define que tipo de variáveis o ponteiro pode apontar.

Endereçona Memória

Conteúdo

1000 1003

1001

1002

1003

1004

1005

1006

Page 3: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Ponteiros

Uma variável ponteiro ocupa duas partes na memória, chamadas de parte de posição e parte de valor.

int *p; (1)*p = 10; (2)

Memória

null

p

Memória

p

10

Parte de Posição

Parte de Valor

Parte de Posição

Efeito da instrução 1 Efeito da instrução 2

Page 4: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Ponteiros

Na instrução 1 a variável p só tem parte de posição e seu conteúdo é null pois ainda não aponta para nenhum endereço.Na instrução 2 é que p terá a parte de valor e a parte de posição terá um endereço (diferente de null).

int *p; (1)*p = 10; (2)

Memória

null

p

Memória

p

10

Parte de Posição

Parte de Valor

Parte de Posição

Efeito da instrução 1 Efeito da instrução 2

Page 5: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Operadores de Ponteiros

Para selecionar cada uma das partes de uma variável ponteiro p, usa-se:

p para especificar a parte de posição da variável p. Pode conter um endereço de memória ou null se não estiver apontado para um valor.

*p para especificar a parte de valor da variável p.

Observação: O operador & serve para especificar o endereço na memória da variável que o segue.

Page 6: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Exemplificando

Suponha que a variável contador usa a posição de memória 2000 para armazenar seu valor. Também assuma que contador tem o valor 100.

int *m; // m e um ponteiro para o tipo intm = &contador; // m recebe o endereço de contadorq = *m // q recebe o valor que está no

// endereço de m

1a. instrucao: A variável m não é do tipo, mas aponta para um valor do tipo int.Após a 2a. instrução m terá o valor 2000. Após a 3a. instrução q terá o valor 100.

Page 7: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte=0, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

Page 8: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte=0, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

fonte destino

m

0 0 NULL

Page 9: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte=0, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

m

NULL

destino0

fonte

10

Page 10: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

mdestino0

fonte

10

Page 11: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

mdestino10

fonte

10

Page 12: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas I?

int destino=0, fonte, *m;fonte = 10;m = &fonte;destino = *m;printf(“%d”, destino);

mdestino10

fonte

10

Page 13: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas II?

int x, *p1, *p2;x = 10;p1 = &x;p2 = p1;printf("%d", *p2)

Page 14: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas II?

int x=10, *p1, *p2;p1 = &x;p2 = p1;printf("%d", *p2)

xp2p1

10NULL NULL

Page 15: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas II?

int x=10, *p1, *p2;p1 = &x;p2 = p1;printf("%d", *p2)

xp2p1

10NULL

Page 16: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas II?

int x=10, *p1, *p2;p1 = &x;p2 = p1;printf("%d", *p2)

xp2p1

10

Page 17: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas II?

int x=10, *p1, *p2;p1 = &x;p2 = p1;printf("%d", *p2)

xp2p1

10

Page 18: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas III?

int a=1, b=2, *pa, *pb;printf("a=%d b=%d\n",a,b);pa=&a;pb=&b;*pa+=5;*pb+=5;printf("a=%d b=%d\n",a,b);

apbpa

1NULL NULL

b

2

Page 19: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas III?

int a=1, b=2, *pa, *pb;printf("a=%d b=%d\n",a,b);pa=&a;pb=&b;*pa+=5;*pb+=5;printf("a=%d b=%d\n",a,b);

apbpa

1NULL NULL

b

2

Page 20: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas III?

int a=1, b=2, *pa, *pb;printf("a=%d b=%d\n",a,b);pa=&a;pb=&b;*pa+=5;*pb+=5;printf("a=%d b=%d\n",a,b);

apbpa

1

b

2

Page 21: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas III?

int a=1, b=2, *pa, *pb;printf("a=%d b=%d\n",a,b);pa=&a;pb=&b;*pa+=5;*pb+=5;printf("a=%d b=%d\n",a,b);

apbpa

6

b

7

Page 22: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Quais as Saídas Produzidas III?

int a=1, b=2, *pa, *pb;printf("a=%d b=%d\n",a,b);pa=&a;pb=&b;*pa+=5;*pb+=5;printf("a=%d b=%d\n",a,b);

apbpa

6

b

7

Page 23: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Cuidado ao Manipular Ponteiros

Onde está o erro no código abaixo?

int x, *p;x = 10;*p = x;

Page 24: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Cuidado ao Manipular Ponteiros

Onde está o erro no código abaixo?

int x, *p;x = 10;*p = x;

O problema do código acima é que estamos atribuindo o conteúdo da variável x para alguma posição da memória desconhecida. Desconhecida porque p não tem parte de valor, só parte de posição (que é null), ou seja, p foi declarada mas nunca apontou para um endereço.

O certo seria:

int x, *p;x = 10;p = &x // p = (int) malloc(sizeof(int));

// *p = x;

Page 25: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Aritmética de Ponteiros

Existem apenas duas operações aritméticas que podem ser utilizadas com ponteiros: adição e subtração.

Cada vez que um ponteiro é incrementado, ele aponta para a posição de memória do próximo elemento de seu tipo base. O mesmo raciocínio quando decrementado.

Vamos analisar as instruções I, II e III:I. Vamos imaginar que p passe a apontar para o endereço 2000.II. Partindo do princípio que cada elemento do tipo int ocupa 2 bytes, o próximo elemento do tipo int está na posição 2002, então p passa a conter 2002 e não 2001. III. Estando p apontando para a posição 2002, ao incremetar 10, p passa a conter 2022.

a = 100;int *p; p=&a;

(I)

p++;

(II)

p=p+10;

(III)

Page 26: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Aritmética de Ponteiros

(I) a = 100;int *p;

p=&a;

(II) p++;

(III) p=p+10;

Page 27: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Comparação de Ponteiros

Qual a saída produzida?

main(){ int a,b,*p,*q; a=10; b=10; p=&a; q=&b; if (p==q) { printf("Valores iguais.\n"); }else{ printf("valores diferentes.\n"); } getch();}

Page 28: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Comparação de Ponteiros

Qual a saída produzida?

main(){ int a,b,*p,*q; a=10; b=10; p=&a; q=&b; if (p==q) { printf("Valores iguais.\n"); }else{ printf("valores diferentes.\n"); } getch();} Porque?

Page 29: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Ponteiros e Vetores

Em C, o nome de um vetor sem índice retorna o endereço inicial do vetor, que é o primeiro elemento. No trecho de código abaixo, p recebe o endereço do 1o. elemento da vetor frase.

char frase[80], *p;p = frase;

Page 30: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Diferentes Formas de Acessar Um Vetor

C fornece dois métodos para acessar os elementos de um vetor: Indexação e Aritmética de ponteiros.

Para acessarmos o 5o. elemento da vetor frase do exemplo anterior usamos uma das formas abaixo:

char frase[80], *p;p = frase;

frase[4] (1)*(p+4) (2)*(frase + 4) (3)p[4] (4)

As linhas 1 e 4 utilizam indexação para acessar o vetor e as linhas 2 e 3 utilizam aritmética de ponteiros.

frase

0

1

2

3

4

...

79

Page 31: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Diferentes Formas de Acessar Um Vetor

main(){int vet[]={10, 20, 30,40,50};

/*Se o nome do vetor sozinho é um ponteiro

para o 1o. elemento, então *(vet) fazreferência ao conteúdo deste endereço.

*/

for (int i=0; i < 5; i++){ printf("%d\n",*(vet+i)); } getch();}

Page 32: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Diferentes Formas de Acessar Um Vetor

int *p=vet; for (int i=0; i < 5; i++){ printf("%d\n",*(p+i)); // ou printf("%d\n",*(vet+i));} /*forma tradicional de se referenciar a um vetor.*/

for (int i=0; i < 5; i++){ printf("%d\n",vet[i]);}

/*Em C qualquer ponteiro pode ser indexado como se fosse um vetor.*/

for (int i=0; i < 5; i++){ printf("%d\n",p[i]);}

1

3

4

2

Page 33: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Vetor de Ponteiros

Ponteiros podem ser organizados em vetores como qualquer outro tipo de dado.

A declaração de um vetor de 10 ponteiros inteiros: int *x[10];

Para atribuir o endereço de uma variável int, chamada num, ao 5o. elemento do vetor de ponteiros: x[4]=&num;

Para acessar a mesma posição seria: *x[4]

Page 34: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

O endereço de um argumento é copiado no parâmetro formal da função. Dentro da função, o endereço é usado para acessar o argumento real utilizado na chamada da função.

Isto significa que alterações feitas nos parâmetros formais afetam os argumentos usados na chamada da função.

Page 35: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

Page 36: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

a

10

b

20

Page 37: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

ayx

10

b

20

Page 38: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

ayx

10

b

20

temp

10

Page 39: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

ayx

20

b

20

temp

10

Page 40: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

ayx

20

b

10

temp

10

Page 41: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Passando Argumentos por Referência

void troca(int *x, int *y);

main(){ int a=10; int b=20; troca(&a,&b); printf("%d %d", a,b); getch();}void troca(int *x,int *y){ int temp; temp=*x; *x=*y; *y=temp;}

a

20

b

10

Page 42: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Vetores como Argumento para uma Função

Em C, quando um vetor é usado como um argumento para uma função, apenas o endereço do primeiro elemento do vetor é passado, não uma cópia do vetor inteiro.

int i[10];func(i);

Podemos declarar o parâmetro formal de três formas:

1. void func(int *x) como um ponteiro

2. void func(int x[10]) como uma matriz dimensionada

3. void func(int x[]) como uma matriz não dimensionada

Podemos verificar que o comprimento da matriz não importa para a função, porque C não realiza verificação de limites. Portanto void func(int x[30]) também funcionaria, porque o compilador C instrui func a receber um ponteiro, ele não cria realmente um vetor de 10 ou de 30 elementos.

Page 43: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Vetores como Argumento para uma Função

#define Max 5

int numeros[MAX]; void mostra(int *p, int n){ for (int i=0; i<n; i++){ printf("\n%d",*(p++)); // ou printf("\n%d",p[i]) }} main(void){ for(int i=0;i<MAX;i++){ numeros[i]=i*10; } mostra(numeros, MAX); getch();}

Page 44: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

Vetores como Argumento para uma Função

Quando um vetor bidimensional é usada como argumento para uma função, apenas um ponteiro para o primeiro elemento é realmente passado. Porém, uma função que recebe um vetor bidimensional como parâmetro, deve definir pelo menos o comprimento da 2a. dimensão. Isto ocorre porque o compilador C precisa saber o comprimento de cada linha para indexar a vetor corretamente.

Exemplo: Uma função que recebe um vetor bidimensional de inteiros 10 x 10 deve ser declarada da seguinte forma: void func (int x[ ] [10]);

É importante entender que, quando um vetor é usado como um argumento para uma função, seu endereço é passado para a função. Portanto existe a possibilidade do conteúdo original da vetor ser alterado.

Função Retornando um Ponteiro

Indicamos que uma função retornará um ponteiro inserindo um * antes do nome da função. int *func();