A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Prof. Ricardo Santos PONTEIROS

Apresentações semelhantes


Apresentação em tema: "Prof. Ricardo Santos PONTEIROS"— Transcrição da apresentação:

1 Prof. Ricardo Santos contato@ricardosantos.net PONTEIROS

2 Ponteiros Um ponteiro é uma variável que contém um endereço de memória
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.

3 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 10 Parte de Posição Parte de Valor Efeito da instrução 1 Efeito da instrução 2

4 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 10 Parte de Posição Parte de Valor Efeito da instrução 1 Efeito da instrução 2

5 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.

6 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 int *m; // m e um ponteiro para o tipo int m = &contador; // m recebe o endereço de contador q = *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 Após a 3a. instrução q terá o valor 100.

7 Quais as Saídas Produzidas I. int destino=0, fonte=0,
Quais as Saídas Produzidas I? int destino=0, fonte=0, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino);

8 Quais as Saídas Produzidas I. int destino=0, fonte=0,
Quais as Saídas Produzidas I? int destino=0, fonte=0, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino); fonte destino m NULL

9 Quais as Saídas Produzidas I. int destino=0, fonte=0,
Quais as Saídas Produzidas I? int destino=0, fonte=0, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino); fonte destino m 10 NULL

10 Quais as Saídas Produzidas I. int destino=0, fonte,
Quais as Saídas Produzidas I? int destino=0, fonte, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino); fonte destino m 10

11 Quais as Saídas Produzidas I. int destino=0, fonte,
Quais as Saídas Produzidas I? int destino=0, fonte, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino); fonte destino m 10 10

12 Quais as Saídas Produzidas I. int destino=0, fonte,
Quais as Saídas Produzidas I? int destino=0, fonte, *m; fonte = 10; m = &fonte; destino = *m; printf(“%d”, destino); fonte destino m 10 10

13 Quais as Saídas Produzidas II. int x,. p1,
Quais as Saídas Produzidas II? int x, *p1, *p2; x = 10; p1 = &x; p2 = p1; printf("%d", *p2)

14 Quais as Saídas Produzidas II. int x=10,. p1,
Quais as Saídas Produzidas II? int x=10, *p1, *p2; p1 = &x; p2 = p1; printf("%d", *p2) p1 p2 x NULL NULL 10

15 Quais as Saídas Produzidas II. int x=10,. p1,
Quais as Saídas Produzidas II? int x=10, *p1, *p2; p1 = &x; p2 = p1; printf("%d", *p2) p1 p2 x NULL 10

16 Quais as Saídas Produzidas II. int x=10,. p1,
Quais as Saídas Produzidas II? int x=10, *p1, *p2; p1 = &x; p2 = p1; printf("%d", *p2) p1 p2 x 10

17 Quais as Saídas Produzidas II. int x=10,. p1,
Quais as Saídas Produzidas II? int x=10, *p1, *p2; p1 = &x; p2 = p1; printf("%d", *p2) p1 p2 x 10

18 Quais as Saídas Produzidas III. int a=1, b=2,. pa,
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); pa pb a b NULL NULL 1 2

19 Quais as Saídas Produzidas III. int a=1, b=2,. pa,
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); pa pb a b NULL NULL 1 2

20 Quais as Saídas Produzidas III. int a=1, b=2,. pa,
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); pa pb a b 1 2

21 Quais as Saídas Produzidas III. int a=1, b=2,. pa,
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); pa pb a b 6 7

22 Quais as Saídas Produzidas III. int a=1, b=2,. pa,
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); pa pb a b 6 7

23 Cuidado ao Manipular Ponteiros Onde está o erro no código abaixo
Cuidado ao Manipular Ponteiros Onde está o erro no código abaixo? int x, *p; x = 10; *p = x;

24 Cuidado ao Manipular Ponteiros Onde está o erro no código abaixo
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;

25 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 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 e não 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)

26 Aritmética de Ponteiros (I) a = 100; int *p; p=&a; (II) p++; (III) p=p+10;

27 Comparação de Ponteiros Qual a saída produzida. main(){ int a,b,. p,
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(); }

28 Comparação de Ponteiros Qual a saída produzida. main(){ int a,b,. p,
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?

29 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;

30 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.

31 Diferentes Formas de Acessar Um Vetor main(){
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) faz referência ao conteúdo deste endereço. */ for (int i=0; i < 5; i++){ printf("%d\n",*(vet+i)); } getch(); }

32 Diferentes Formas de Acessar Um Vetor int. p=vet;
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 2 3 4

33 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]

34 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.

35 Passando Argumentos por Referência void troca(int. x, int
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; }

36 Passando Argumentos por Referência void troca(int. x, int
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 b 10 20

37 Passando Argumentos por Referência void troca(int. x, int
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; } x y a b 10 20

38 Passando Argumentos por Referência void troca(int. x, int
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; } x y a b 10 20 temp 10

39 Passando Argumentos por Referência void troca(int. x, int
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; } x y a b 20 20 temp 10

40 Passando Argumentos por Referência void troca(int. x, int
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; } x y a b 20 10 temp 10

41 Passando Argumentos por Referência void troca(int. x, int
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 b 20 10

42 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.

43 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(); }

44 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();


Carregar ppt "Prof. Ricardo Santos PONTEIROS"

Apresentações semelhantes


Anúncios Google