Baixe o app para aproveitar ainda mais
Prévia do material em texto
Algoritmos e Estruturas de Dados | BLU 3202 Algoritmos e estruturas de Dados Ponteiros Prof. Denis Brandl 1 Algoritmos e Estruturas de Dados | BLU 3202 Variáveis ▪ Armazenam dados ▪ Tipos: Int, float, double, char, struct #include <stdio.h> int main() { int a[3] = {2017,2018,2019}; for (int i=0;i<3;i++) { printf("%d\n",a); } } 2 Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros ▪ São variáveis cujos valores são endereços de memória de outras variáveis; ▪ Ao invés de guardar dados (números, palavras) são guardados endereços de memória; ▪ Variáveis referenciam valores diretamente; ▪ Ponteiros referenciam valores indiretamente (“apontam”) ▪ Analogias: ▪ Ponteiros de um relógio ▪ Documentos e Pastas ▪ Em C são utilizados tipicamente em: ▪ Vetores/Strings ▪ Passagem de argumentos a funções por referência ▪ Alocação dinâmica de memória ▪ Para retornar mais de um valor em uma função. ▪ Referência para listas, pilhas, árvores e grafos. 3 Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros ▪ tipo: é o tipo da variável para a qual ele aponta ▪ * : (dereferenciador) indica que a variável será um ponteiro ▪ nome_ponteiro: O nome da variável ponteiro ▪ Um ponteiro só pode receber endereço de variáveis do mesmo tipo 4 Sintaxe de declaração de um ponteiro tipo *nome_ponteiro ... int *nome_ponteiro; float *outro_ptr; ... float a,b,c,*d,e; ... MISTURAR DECLARAÇÕES Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros ▪ Ponteiros não inicializados apontam para lugar indefenido; ▪ Pode ter o valor NULL (Nulo) int variavel; int variavel = 1 int *p; int *p = NULL; ▪ Ou pode apontar para uma variável que já existe... 5 Algoritmos e Estruturas de Dados | BLU 3202 6 Operador de referência: ▪ Permite retorna o endereço na memória de seu operando ▪ & : retorna o endereço da variável; ... int a = 12; // t1 int *a_ptr; // t2 a_ptr = &a; // t3 *a_ptr = 100; // t4 ... Sintaxe: &nome_variável Endereços5000 5001 5002 5003 5004 5005 t0 Memória Variáveis 12t1 Memória Variáveisa 12t2 Memória Variáveisaa_ptr 125003t3 Memória Variáveisaa_ptr 1005003t4 Memória Variáveisaa_ptr Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Dica 7 Operadores: ▪ Ao interpretar um programa fazer as associações: ▪ &: o endereço de memória da variável; ▪ *: o conteúdo do endereço de memória indicado pela variável (ponteiro); Algoritmos e Estruturas de Dados | BLU 3202 8 #include <stdio.h> int main(){ int a = 10; int *a_ptr = &a; printf("valor estatico de a: %d\n",a); printf("endereco de memoria onde esta o valor de a:%\n",&a); printf("endereco de memoria armazenado no ponteiro a_ptr: %p\n",a_ptr); printf("conteudo do endereco de memoria armazenado em a_ptr: %d\n",*a_ptr); printf("conteudo do endereco de memoria armazenado da variavel a: %d\n",*(&a)); } valor estatico de a: 10 endereco de memoria onde esta o valor de a: 000000000022FE44 endereco de memoria armazenado no ponteiro a_ptr: 000000000022FE44 conteudo do endereco de memoria armazenado em a_ptr: 10 conteudo do endereco de memoria armazenado da variavel a: 10 Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 1 9 #include <stdio.h> int main(){ int a = 3, b = 7; int *p1, *p2; p2 = p1 = &a; *p1 = 5; p2 = &b; printf("%d - %d",*p1,*p2); } O que imprime e qual o estado das variáveis em cada ponto de execução do código? Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 1 10 p1 ? p2 ? a 3 b 7100 104 200 290 #include <stdio.h> int main(){ int a = 3, b = 7; int *p1, *p2; p2 = p1 = &a; *p1 = 5; p2 = &b; printf("%d - %d",*p1,*p2); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 1 11 p1 100 p2 100 a 3 b 7100 104 200 290 #include <stdio.h> int main(){ int a = 3, b = 7; int *p1, *p2; p2 = p1 = &a; *p1 = 5; p2 = &b; printf("%d - %d",*p1,*p2); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 1 12 p1 100 p2 100 a 5 b 7100 104 200 290 #include <stdio.h> int main(){ int a = 3, b = 7; int *p1, *p2; p2 = p1 = &a; *p1 = 5; p2 = &b; printf("%d - %d",*p1,*p2); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 1 13 p1 100 p2 104 a 5 b 7100 104 200 290 #include <stdio.h> int main(){ int a = 3, b = 7; int *p1, *p2; p2 = p1 = &a; *p1 = 5; p2 = &b; printf("%d - %d",*p1,*p2); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Operações 14 ▪Somente é possível somar e subtrair valores INTEIROS #include <stdio.h> int main() { int p = 0x5DC; // Pos 1500 printf("p = %d \n",p); p++; printf("p = %d \n",p); p = p + 15; printf("p = %d \n",p); p = p - 2; printf("p = %d \n",p); } ??? ? Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Operações 15 #include <stdio.h> int main() { int p = 0x5DC; // Pos 1500 printf("p = %d \n",p); p++; printf("p = %d \n",p); // Pos 1504 p = p + 15; printf("p = %d \n",p); p = p - 2; printf("p = %d \n",p); } Um valor inteiro ocupa 4 espaços de 1 Byte 1500 1501 1502 1503 ??? ? Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Operações 16 #include <stdio.h> int main() { int p = 0x5DC; // Pos 1500 printf("p = %d \n",p); p++; printf("p = %d \n",p); p = p + 15; printf("p = %d \n",p);// Pos 1564 p = p - 2; printf("p = %d \n",p); } 1504 1505 ... 1564 ??? ? p = 2 * Tamanho inteiro p = p + (15*4) Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Operações 17 #include <stdio.h> int main() { int p = 0x5DC; // Pos 1500 printf("p = %d \n",p); p++; printf("p = %d \n",p); p = p + 15; printf("p = %d \n",p); p = p - 2; printf("p = %d \n",p);// Pos 1556 } 1504 1505 ... 1564 p = 2 * Tamanho inteiro p = p - (2*4) Algoritmos e Estruturas de Dados | BLU 3202 Tipos de dados: 18 TIPO TAMANHO CHAR 1 byte INT 4 bytes FLOAT 4 bytes DOUBLE 8 bytes Algoritmos e Estruturas de Dados | BLU 3202 Aritmética de Ponteiros 19 ▪Incremento ou decremento - exemplos: // incrementa ptr em 1: 1*(tipo de dado) ptr++; // incrementa ptr em 2: 2*(tipo de dado) ptr = ptr + 2; ▪Se ptr for um ponteiro para um int (4 bytes): // incrementa ptr em 1: 1*(4) ptr++; // incrementa ptr em 2: 2*(4) ptr = ptr + 2; ▪Se ptr for um ponteiro para um double (8 bytes): // incrementa ptr em 1: 1*(8) ptr++; // incrementa ptr em 2: 2*(8) ptr = ptr + 2; Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Comparações 20 ▪Podem ser comparados usando: ▪ ==, !=, >, <, >=, <= #include <stdio.h> int main() { int *p1, *p2, x, y; p1 = &x; p2 = &y; if (p1 == p2) { printf("Ponteiros Iguais"); } else { printf("Ponteiros Diferentes"); } } Questão: p1 e p2 apontam para o mesmo endereço? Algoritmos e Estruturas de Dados | BLU 3202 Aritmética de Ponteiros 21 Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros como parâmetros para funções 22 Passagem por valor: ▪ Ao longo da função, o parâmetro recebido é uma cópia da variável recebida; ▪ Consequência: alterações feitas na variável passada como parâmetro, no decorrer da função, não afetam a variável no programa principal; Passagem por referência (com ponteiros): ▪ O parâmetro na função é um ponteiro para o endereço de memória onde está o valor do parâmetro; ▪ Consequência: alterações feitasna variável (ponteiro) passada como parâmetro, no decorrer da função, afetam a variável no programa principal; Algoritmos e Estruturas de Dados | BLU 3202 23 #include <stdio.h> void swap1(int x, int y){ int z = x; x = y; y = z; } void swap2(int *x, int *y){ int z = *x; *x = *y; *y = z; } int main(){ int a = 10, b = 20; swap1(a,b); printf("Valor de a-b: %d - %d\n",a,b); swap2(&a,&b); printf("Valor de a-b: %d - %d\n",a,b); } Saída: Valor de a-b: 10 - 20 Valor de a-b: 20 - 10 x e y são ponteiros com o endereço de memória das variáveis a e b (parâmetros passados por referência) x e y são variáveis locais da função e possuem uma cópia do valor de a e b (parâmetros passados por valor) Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 24 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } O que imprime e qual o estado das variáveis em cada ponto de execução do código? Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 25 a 5 b 7 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 26 a 5 x 1011 a 5 b 7 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 27 a 5 x 1011 a 5 b 7 S 1 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 28 a -5 x 1011 a 5 b 7 S 1 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 29 a -5 x 1011 a 5 b -25 S 1 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – exemplo 2 30 a 5 b -25 #include <stdio.h> void func(int a, int *x){ int s = a%2; a = (1-2*s)*a; *x = a*5; } int main(){ int a = 5, b = 7; func(a, &b); printf("%d-%d",a,b); } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros – em memória ▪Na realidade os ponteiros são também variáveis ▪ São guardados em memória em conjunto com as variáveis restantes ▪ Têm um endereço associado ▪ Podem ser "apontados" por outro ponteiro 31 var1 var2 ptr1 ptr2 var3 var4 ptr3 var5 ptr4 Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros para ponteiros 32 a 5 a_ptr &a b_ptr &a_ptr #include <stdio.h> int main() { int a, *a_ptr, **b_ptr; a=5; a_ptr = &a; b_ptr= &a_ptr; printf("Val = %d", b_ptr); printf("Val = %d", *b_ptr); printf("Val = %d", **b_ptr); } a 5 a_ptr 1000 b_ptr 1004 1004 1000 1008 A quantidade * indica a quantidade de ponteiros! Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros para structs O operador -> facilita o acesso às variáveis da struct – evita o uso de () 33 #include <stdio.h> struct ParV { int a,b; }; int main(){ ParV pa; ParV *p2 = &pa; // acessar a struct (*p2).a = 3; (*p2).b = 5; } #include <stdio.h> struct ParV { int a,b; }; int main(){ ParV pa; ParV *p2 = &pa; // ou usar o operador -> p2->a = 3; p2->b = 5; } Algoritmos e Estruturas de Dados | BLU 3202 Vetores, ponteiros e Alocação Dinâmica 34 ▪Vetor: Conjunto de dados armazenados de forma sequencial ▪Na linguagem C o nome de um vetor corresponde ao endereço do seu primeiro elemento, isto é, se v é um vetor v == &v[0] ▪Existem 2 formas de colocar um ponteiro apontando para o primeiro elemento de um vetor: int v[3] = {10,20,30}; int *ptr; ptr = &v[0]; // primeira forma ptr = v; // segunda forma Algoritmos e Estruturas de Dados | BLU 3202 Vetores, ponteiros e Alocação Dinâmica * ▪Também é possível apontar para outros elementos do vetor: ptr = &v[2]; ▪Este conceito é um dos dogmas centrais da manipulação de vetores através de ponteiros na linguagem C; ▪Usando a aritmética de ponteiros (será mostrado na sequência, é possível manipular os elementos de vetores e matrizes através de seus endereços de memória; Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Vetores 36 #include <stdio.h> int main() { int a[3] = {2018,0,0}; for (int i =0;i<3;i++) { printf("%d\n",a[i]); } } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros - Vetores 37 #include <stdio.h> int main() { int a[3] = {2018,0,0}; for (int i =0;i<3;i++) { printf("%d\n",*a + i); } } Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros Genéricos 38 ▪Pode apontar para todos os tipos de dados existentes ou que ainda será criado: void *ponteiroGenerico; int *p1, p2 = 10; p1 = &p2; ponteiroGenerico = &p2; printf(“Endereço em ponteiroGenerico: %p”,ponteiroGenerico); ponteiroGenerico = &p1; printf(“Endereço em ponteiroGenerico: %p”,ponteiroGenerico); ponteiroGenerico = p1; printf(“Endereço em ponteiroGenerico: %p”,ponteiroGenerico); Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros Genéricos 39 void *ponteiroGenerico; void *ponteiroGenerico; int p2 = 10; ponteiroGenerico = &p2; // Endereço de inteiro printf("Conteudo: %d\n",*ponteiroGenerico); Questão: Quantas posições de memória ponteiroGenerico deve pegar? ??? Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros Genéricos 40 void *ponteiroGenerico; void *ponteiroGenerico; int p2 = 10; ponteiroGenerico = &p2; // Endereço de inteiro printf("Conteudo: %d\n",*(int*)ponteiroGenerico); ponteiroGenerico será convertido para o tipo Inteiro Algoritmos e Estruturas de Dados | BLU 3202 Ponteiros Genéricos - Dica 41 ▪As operações aritméticas sempre são realizadas com base em uma unidade de memória: void *ponteiroGenerico = 0x5DC; // 1500 p++; // 1501 p = p + 15; // 1516 p = p - 2; // 1514
Compartilhar