Ponteiro Definição de variável apontadora Aritmética de ponteiros Ponteiros e vetores Funções e passagem por referência Structs e ponteiros Alocação dinâmica de memória
Objetivo Ponteiro Ponteiro Compreender a definição e dominar a implementação de ponteiros em C.
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4;
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 32 bits 151266124 endereço conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 32 bits 151266124 endereço conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 32 bits 151266124 endereço Célula Célula Célula Célula conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 32 bits 1 byte 1 byte 1 byte 1 byte 151266124 endereço Célula Célula Célula Célula conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 151266124 32 bits 1 byte 1 byte 1 byte 1 byte endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 32 bits 1 byte 1 byte 1 byte 1 byte 151266124 endereço = 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 151266124 32 bits 1 byte 1 byte 1 byte 1 byte endereço 151266124 151266125 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 151266124 32 bits 1 byte 1 byte 1 byte 1 byte endereço 151266124 151266125 151266126 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 1º: alocação de espaço de armazenamento com endereçamento para permitir o acesso a este espaço. x 151266124 32 bits 1 byte 1 byte 1 byte 1 byte endereço 151266124 151266125 151266126 151266127 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 2º: atribuição de valor de acordo com o tipo definido no espaço de conteúdo. x 32 bits 151266124 endereço 4 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 2º: atribuição de valor de acordo com o tipo definido no espaço de conteúdo. x 151266124 endereço 151266124 151266125 151266126 151266127 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; 2º: atribuição de valor de acordo com o tipo definido no espaço de conteúdo. x 151266124 endereço 00000000 00000000 00000000 00000100 151266124 151266125 151266126 151266127 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; int y;
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int y; 151266124 endereço 4 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int y; y 151266124 endereço 4 conteúdo 151266128 endereço 165564619 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int y; y = x; 151266124 4 y endereço conteúdo 131233128 endereço 4 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; 151266124 endereço 4 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p 151266124 endereço 4 conteúdo 151266128 endereço 5156161515 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 4 p endereço conteúdo 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 4 p endereço conteúdo 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 4 endereço conteúdo *p = 10; p 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 4 endereço conteúdo *p = 10; p 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 4 endereço conteúdo *p = 10; p 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 10 endereço conteúdo *p = 10; p 151266128 endereço 151266124 conteúdo
Como ocorre a declaração e atribuição de valores em variáveis de tipos primitivos? int x = 4; x int* p; p = &x; 151266124 10 endereço conteúdo *p = 10; p 151266128 endereço 151266124 conteúdo
Variáveis Apontadoras Como visto, qualquer variável tem um nome, conteúdo e endereço. Uma variável apontadora é um caso particular em que o valor (inteiro) que ela contém é um endereço de memória.
Variáveis Apontadoras Como visto, qualquer variável tem um nome, conteúdo e endereço. Uma variável apontadora é um caso particular em que o valor (inteiro) que ela contém é um endereço de memória. Observe que uma variável apontadora sempre armazenará valores inteiros.
Variáveis Apontadoras - Declaração <tipoapontado> * <nome> ; Exemplos: int* p1; char* p2; float* p3, p4;//p4 será uma variável comum float *p3, *p4;//p4 será uma variável ponteiro double* p4;
Operador de Endereço (&) Retorna o endereço de uma variável; Útil interpretá-la como endereço de. Exemplo: int x = 4; int* px; px = &x; //px recebe o endereço de x
Operador Apontador (*) Pode-se atribuir um valor à variável apontada pelo ponteiro. Útil interpretá-lo como o conteúdo apontado por.
Exemplo: int x = 4; int* px = &x; *px = 10; Ponteiro Ponteiro Operador Apontador (*) o conteúdo apontado por px receberá o valor 10. No caso, o conteúdo da variável x;
Operador Apontador (*) Posso atribuir a uma variável do tipo int um endereço de uma variável? Sim. (Ex: int x, y; x = &y;) Posso alterar o conteúdo de uma variável utilizando o operador apontador em uma variável do tipo int que está armazenando um endereço de memória? Não. (Ex: int x, y; x = &y; *x = 10; //erro de compilação)
Ponteiros e operações aritméticas Posso efetuá-las com ponteiros? Sim, lembre-se que as operações serão efetuadas em endereços, já que ponteiros armazenam endereços. As operações possíveis com ponteiros são as de soma (+), subtração (-), incremento (++) e decremento (--).
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238 int* p = &x; //p = 1234
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238 int* p = &x; //p = 1234 p = p + 1; // p = 1238
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238 int* p = &x; //p = 1234 p = p + 1; // p = 1238 p = p 1; // p = 1234
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238 int* p = &x; //p = 1234 p = p + 1; // p = 1238 p = p 1; // p = 1234 p++; // p = 1238
Ponteiros e operações aritméticas Operações com ponteiros de inteiros: int x = 10; //supondo &x = 1234 int y = 20; //então, &y = 1238 int* p = &x; //p = 1234 p = p + 1; // p = 1238 p = p 1; // p = 1234 p++; // p = 1238 P--; // p = 1234
Ponteiros e operações aritméticas Operações com ponteiros de reais (double): double x; //supondo &x = 1238 double y; //então, &y = 1246 double* p = &x; //p = 1238 p = p + 1; // p = 1246 p = p 1; // p = 1238 p++; // p = 1246 P--; // p = 1238
Ponteiros e operações aritméticas Operações com ponteiros de char: char x; //supondo &x = 1231 char y; //então, &y = 1232 char* p = &x; //p = 1231 p = p + 1; // p = 1232 p = p 1; // p = 1231 p++; // p = 1232 P--; // p = 1231
Vetores e ponteiros Como se sabe, em uma variável simples, ao efetuarmos tal comando, int x = 20, y; y = x; no lugar do nome x, é retornado o valor da variável. Para retornarmos seu endereço, utilizamos: y = &x;
Vetores e ponteiros O que aconteceria se fizéssemos esse comando com um vetor? int vet[5]; int* x = vet; O nome de um vetor atribuído a uma variável retorna o endereço do próprio vetor.
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet índices 0 1 2 3 4 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 1115 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 1115 1119 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 1115 1119 1123 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 índices 0 1 2 3 4 1111 1115 1119 1123 1127 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 vet 1111 1115 1119 1123 1127 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; p 1107 endereço 1111 conteúdo vet 1111 1115 1119 1123 1127 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; *p = 10; p 1107 endereço 1111 conteúdo vet 1111 1115 1119 1123 1127 10 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1115 endereço conteúdo vet 1111 1115 1119 1123 1127 10 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1115 *p = 20; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1119 endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1119 *p = 30; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1123 endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1123 *p = 40; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 40 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1127 endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 40 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p++; p 1107 1127 *p = 50; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 40 50 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p--; p 1107 1123 *p = 50; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 30 50 50 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p--; p 1107 1119 *p = 50; endereço conteúdo vet 1111 1115 1119 1123 1127 10 20 50 50 50 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p--; p 1107 1115 *p = 50; endereço conteúdo vet 1111 1115 1119 1123 1127 10 50 50 50 50 conteúdo conteúdo conteúdo conteúdo conteúdo
Vetores e ponteiros Como funciona o endereçamento de um vetor? int vet[5]; //supondo vet = 1111 int* p = vet; // p = 1111... p--; p 1107 1111 *p = 50; endereço conteúdo vet 1111 1115 1119 1123 1127 50 50 50 50 50 conteúdo conteúdo conteúdo conteúdo conteúdo
Ponteiros como argumentos de funções Como trocar valores entre duas variáveis na função? void troca(int x, int y) { int temp; temp = x; x = y; y = temp; }
Ponteiros como argumentos de funções Como trocar valores entre duas variáveis na função? int main() { int a = 4, b = 2; troca(a,b); printf ( %d %d\n,a,b); return 0; } O VALOR NÃO É TROCADO NA MAIN!
Ao chamar a função: troca(a,b); Ponteiro Ponteiro Ponteiros como argumentos de funções
Ponteiros como argumentos de funções Ao chamar a função: troca(a,b); Na passagem de parâmetros, efetivamente seria como se fizéssemos o seguinte comando: x = a; y = b;
Ponteiros como argumentos de funções Ao chamar a função: troca(a,b); Na passagem de parâmetros, efetivamente seria como se fizéssemos o seguinte comando: x = a; y = b; Os valores internos das variáveis a e b após a chamada da função são realmente alterados?
Ponteiros como argumentos de funções Este tipo de passagem de parâmetros é comumente chamada de Passagem por Valor
Ponteiros como argumentos de funções Como trocar valores entre duas variáveis na função? void troca(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; }
Ponteiros como argumentos de funções Como trocar valores entre duas variáveis na função? int main() { int a = 4, b = 2; troca(&a,&b); printf ( %d %d\n,a,b); return 0; } O VALOR É TROCADO NA MAIN!
Ao chamar a função: troca(&a,&b); Ponteiro Ponteiro Ponteiros como argumentos de funções
Ponteiros como argumentos de funções Ao chamar a função: troca(&a,&b); Na passagem de parâmetros, efetivamente seria como se fizéssemos o seguinte comando: x = &a; y = &b;
Ponteiros como argumentos de funções Ao chamar a função: troca(&a,&b); Na passagem de parâmetros, efetivamente seria como se fizéssemos o seguinte comando: x = &a; y = &b; Os valores internos das variáveis a e b após a chamada da função são alterados, pois ocorreu a troca de valores referentes às variáveis que possuem os endereços de memória &a e &b.
Ponteiros como argumentos de funções Este tipo de passagem de parâmetros é comumente chamada de Passagem por Referência
Vetores como argumentos de funções Vetores são passados como parâmetros em funções por referência ou valor? void atribui_valor(int *vet,int tam, int valor) { int i; for (i = 0; i<tam; i++) vet[i] = valor; }
Vetores como argumentos de funções Logo, quando fazíamos: void função(int vet[]); para recebermos um vetor passado como argumento, estamos fazendo EXATAMENTE: void função(int *vet); Portanto, em C: vet[] *vet
Exemplo 1 Ponteiro Ponteiro Um função que inicializa um vetor: int* inicializavet (int tam){ int i; int vet = malloc(tam*sizeof(int)); for (i=0; i<tam; i++){ *(vet + i) = 0; } return vet; }
Exemplo 2 Ponteiro Ponteiro Uma função de leitura de duas variáveis: int leituraxy(int* x, int* y){ printf( Entre com as coordenadas ); scanf( %d %d,x,y); }
Exemplo 3 Ponteiro Ponteiro Uma função que compara duas strings: int comparastring(char* str1, char* str2){ char *i,*j; for ( i = str1, j = str2; *i!= '\0' && *j!= '\0' && *i == *j; i++, j++ ); return *i - *j; }
Exemplo 4 Ponteiro Ponteiro Uma função que compara duas strings: int comparastring(char* str1, char* str2){ char i; for ( i = 0; str1[i]!='\0' && str2[i]!='\0' && str1[i]==str2[i]; i++ ); return str1[i] str2[i]; }
Estruturas e ponteiros Como em qualquer outro tipo de dado, ponteiros para estruturas também podem ser definidos. typedef struct{ int x; int y; }Ponto;
Estruturas e ponteiros int main() { Ponto p, *ponteirop; ponteirop = &p; (*ponteirop).x = 1; (*ponteirop).y = 2; return 0; }
Estruturas e ponteiros A forma de referenciar o conteúdo da struct apontada pelo ponteiro é sempre da forma: (*ponteiro).atributo sendo que os parenteses são necessários, devido a precedência superior do operador. se comparado com *.
Estruturas e ponteiros Acessar uma struct apontada por um ponteiro para muitos pode parecer confusa. É muito comum errar os parenteses necessários para garantir a precedência dos operadores. e *.
Estruturas e ponteiros Acessar uma struct apontada por um ponteiro para muitos pode parecer confusa. É muito comum errar os parenteses necessários para garantir a precedência dos operadores. e *. Pensando nisso, os projetistas de C definiram um operador adicional denominado operador seta ( -> ), com a missão de facilitar o acesso aos membros de uma struct.
Dessa forma, Ponteiro Ponteiro Estruturas e ponteiros (*p).atr; p->atr;
Alocação Dinâmica de Memória Objetivos: Utilizar espaços da memória de tamanho arbitrário; Criar estruturas de dados usando encadeamento; É a base do conceito da alocação por demanda, dinâmica.
Alocação Dinâmica de Memória Motivação: Alocação de espaço sob demanda: Muitas vezes o espaço de memória necessário para um conjunto de dados varia durante a execução do programa. Dessa forma, a alocação dinâmica permite que quando for preciso utilizar algum recurso de memória, este seria alocado enquanto o programa estivesse em execução.
Alocação Dinâmica de Memória Funções para alocação dinâmica: Funções principais: - malloc() Aloca um espaço na memória e retorna um ponteiro para o espaço alocado - free() - Libera espaço alocado na memória para que possa ser utilizados por outras aplicações ou por outras chamadas de malloc().
Alocação Dinâmica de Memória Exemplo 1 Alocação Estática int main() { int vet[100]; int n; scanf( %d,&n); //alocação estática em tempo de execução int vet2[n]; return 0; }
Alocação Dinâmica de Memória Exemplo 2 Alocação Dinâmica int main() { int *vet1 = malloc(100*sizeof(int)); int n; scanf( %d,&n); int *vet2 = malloc(n*sizeof(int)); return 0; }
Alocação Dinâmica de Memória Exemplo 3 Alocando string dinamicamente int main() { char* vet = malloc(100*sizeof(char)); scanf( %s,vet); }
Alocação Dinâmica de Memória Liberando espaços com free(): Sempre que um espaço alocado fica sem referência este é perdido, não podendo ser utilizado novamente (memory leak). Antes de fazer um apontador apontar para outro espaço, ou quando o espaço não for mais utilizado, a área de memória que este aponta deve ser liberada com free: a = malloc(10*sizeof(int));... free(a); // O espaço de memória alocado dinâmicamente foi liberado!