prof. ricardo santos [email protected] ponteiros
TRANSCRIPT
![Page 2: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/2.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/3.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/4.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/5.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/6.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/7.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/8.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/9.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/10.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/11.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/12.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/13.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/14.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/15.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/16.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/17.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/18.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/19.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/20.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/21.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/22.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/23.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/24.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/25.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/26.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/27.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/28.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/29.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/30.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/31.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/32.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/33.jpg)
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]=#
Para acessar a mesma posição seria: *x[4]
![Page 34: Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/34.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/35.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/36.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/37.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/38.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/39.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/40.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/41.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/42.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/43.jpg)
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](https://reader035.vdocuments.net/reader035/viewer/2022062219/552fc13f497959413d8de49a/html5/thumbnails/44.jpg)
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();