Baixe o app para aproveitar ainda mais
Prévia do material em texto
BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 1 Ponteiros BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 2 Ponteiros ■ Um ponteiro é um endereço de memória. ■ Seu valor indica onde uma variável está armazenada, não o que está armazenado. ■ Um ponteiro proporciona um modo de acesso a uma variável sem referenciá- la diretamente. 3 Ponteiro • O valor do ponteiro xPtr é o endereço da variável x que, por sua vez, contém o valor 10.0. • O nome de variável x referencia diretamente um valor, sendo que o ponteiro xPtr referencia indiretamente um valor. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 4 Ponteiro ■ Os ponteiros são usados em situações em que o uso de uma variável é difícil ou indesejável. Algumas razões para o uso de ponteiros são: ○ Manipular elementos de matrizes; ○ Receber argumentos em procedimentos e funções que necessitem modificar o argumento original (passagem de parâmetros por referência); ○ Criar estruturas de dados complexas, como listas encadeadas e árvores binárias, onde um item deve conter referências a outro; ○ Alocar e desalocar memória do sistema. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 5 Ponteiro ■ A memória de um computador pode ser vista como uma enorme seqüência de bytes contíguos. ■ Cada byte está localizado em um endereço da memória. O primeiro byte ocupa o endereço 0 da memória; o segundo byte fica no endereço 1 e assim sucessivamente. ■ O endereço é, portanto, um número que indica a posição de um determinado byte na memória. ■ A grandeza desse número varia de sistema para sistema. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 6 Ponteiro ■ Ao declarar uma variável, damos a ela um nome e um tipo. A partir dessas informações, o compilador é capaz de saber o número de bytes que a variável necessita ocupar na memória, de modo a conter qualquer um dos possíveis valores implicitamente especificados através do seu tipo. ■ O compilador também sabe o endereço exato onde a variável se encontra, pois é ele mesmo que cuida de reservar o espaço necessário. ■ O endereço de uma variável que ocupa mais de um byte na memória é o endereço do seu primeiro byte. Quando o nome da variável aparece posteriormente em algum comando, o compilador sabe gerar o código necessário para localizar a variável, seja para guardar nela algum valor, seja para ler o seu valor corrente. ■ Dessa forma um ponteiro é uma variável cujo conteúdo é um endereço de memória. Ao invés de conter o próprio dado, um ponteiro contém o endereço do dado. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 7 Ponteiro – Declaração de Ponteiros ■ A declaração de um tipo ponteiro requer o uso do símbolo * seguido de um identificador. ■ Esse identificador é o chamado tipo base, cuja área será alocada dinamicamente. Por exemplo: int *P; ■ A variável P é um ponteiro para um inteiro. Uma referência à variável P é uma referência ao seu conteúdo, ou seja, a um endereço. 8 Ponteiro - Operadores ■ & - operador de endereço: obtém o endereço na memória de uma variável; ■ * - operador de indireção, também chamado de derreferência: obtém o valor da variável apontada. 9 Ponteiro 10 Ponteiro 11 Ponteiro #include <iostream> using namespace std; int main() { float x; // x é uma variável do tipo float float *xPtr; // xPtr é um ponteiro para um float x = 10.0; xPtr = &x; // xPtr recebe o endereço de x cout << "O valor de x e: " << x << endl; cout << "O endereco de x e: " << &x << endl; cout << "O valor de xPtr e: " << xPtr << " que e o mesmo endereco de x"<< endl; cout << "O valor de *Ptr e " << *xPtr << " que e o mesmo valor de x" << endl; cout << "O endereco de xPtr e: " << &xPtr << endl; return 0; } 12 Inicialização de Ponteiros ■ Com o valor 0 ou a constante NULL: não aponta para nada. Em C++ é preferível usar a constante 0. int *x = 0; int *y = NULL; ■ Com algum endereço de memória de uma variável já existente. int a = 10; int *x = &a; ■ Com a atribuição de um endereço de memória retornado pelo comando new() de alocação dinâmica de memória. int *y = new int(); BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 13 Ponteiros – Constante NULL int *P; P = NULL; ■ Pode-se atribuir NULL a qualquer ponteiro, e também podemos testar se um ponteiro é igual ou diferente de NULL. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 14 Ponteiros - O operador de endereços & - Exemplo /* ProgC046 - Programa para exemplo do operador de endereço & */ #include <iostream> int main() { int *P, I; I = 10; P = &I; std::cout << *P << "\n"; system ("pause"); return 0; } Declaração de um ponteiro de inteiros. P recebe o endereço de I, ou seja, P “aponta” para I. Apresentação do valor de P, que será o mesmo de I, ou seja, 10. 15 Ponteiro - Passagem de Parâmetro ■ Ponteiros na chamada por referência podem ser usados para modificar uma ou mais variáveis da função chamadora, ou para evitar sobrecarga através da passagem por valor de dados grandes. ■ Quando se chama uma função com parâmetros que devem ser modificados, os endereços dos parâmetros devem ser passados. 16 Ponteiro - Passagem de Parâmetro /* funcao troca */ #include <iostream> void troca (int *px, int *py ) { int temp; temp = *px; *px = *py; *py = temp; } int main () { int a = 5, b = 7; troca(&a, &b); std::cout << "a: "<< a << " b: " << b << "\n"; return 0; } 17 Ponteiro - Passagem de Parâmetro BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 18 Operações com Ponteiros ■ C++ permite várias operações básicas com ponteiros. ■ O próximo exemplo imprime os resultados de cada operação, o valor do ponteiro, o valor da variável apontada e o endereço do próprio ponteiro. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 19 Operações com Ponteiros - Exemplo /* ProgC047 - Programa que apresenta as operações com ponteiros */ #include <iostream> int main(){ int A=5, B=6; int *ptrA, *ptrB; ptrA = &A; ptrB = &B; if (ptrA < ptrB) std::cout << "\nptrB-ptrA= " << (ptrB- ptrA); else std::cout << "\nptrA-ptrB= " << (ptrA- ptrB); std::cout << "\nptrA = " << ptrA << ", *nptrA = " << *ptrA << ", &nptrA = " << &ptrA; std::cout << "\nptrB = " << ptrB << ", *nptrB = " << *ptrB << ", &nptrB = " << &ptrB; ptrB++; std::cout << "\nptrB = " << ptrB << ", *nptrB = " << *ptrB << ", &nptrB = " << &ptrB; ptrA = ptrB + 3; std::cout << "\nptrA = " << ptrA << ", *nptrA = " << *ptrA << ", &nptrA = " << &ptrA << "\n \n"; system ("pause"); return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 20 Operações com Ponteiros ■ É possível incrementar (ou decrementar) um ponteiro por meio de adição (ou subtração) regular ou dos operadores de incremento e decremento. ■ Incrementar um ponteiro acarreta sua movimentação para o próximo tipo apontado; isto é, se ptrA é um ponteiro para uma variável int, depois de executar a instrução: ptrA++; ■ o valor de ptrA será incrementado de um int (4 bytes). Cada vez que ptrA for incrementada, apontará para o próximo int da memória. ■ Também é possível somar ou subtrair números inteiros a variáveis ponteiros. A instrução: ptrA = ptrB + 3; ■ fará com que ptrB caminhe 3 inteiros adiante de ptrA.■ Também é possível encontrar a diferença entre dois ponteiros. Esta diferença será expressa em número de tipo apontado entre eles. ■ Testes relacionais são aceitos somente entre ponteiros do mesmo tipo. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 21 Ponteiros e Matrizes ■ Em C++, o relacionamento entre ponteiros e matrizes é muito estreito. ■ O compilador transforma matrizes em ponteiros na compilação, pois a arquitetura do microcomputador compreende ponteiros, e não matrizes. ■ Qualquer operação que pode ser feita com índices de uma matriz pode ser feita com ponteiros. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 22 Ponteiros e Matrizes - Exemplo /*ProgC048 - Programa que mostra a notação de matriz 25/11/2008 - Fabiana Costa Guedes */ #include <iostream> int main(){ int M[5]={1, 2, 3, 4, 5}; for (int i=0; i<5; i++) std::cout << "\n" << M[i]; system ("pause> NULL"); return 0; } Declaração e inicialização da matriz. Apresentação dos dados da matriz na tela. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 23 Ponteiros e Matrizes - Exemplo /*ProgC049 - Programa que mostra a notação de matriz com ponteiro - 25/11/2008 - Fabiana Costa Guedes */ #include <iostream> int main(){ int M[5]={1, 2, 3, 4, 5}; for (int i=0; i<5; i++) std::cout << "\n" << *(M+i); system ("pause>NULL"); return 0; } Declaração e inicialização da matriz. Apresentação dos dados da matriz na tela. Ponteiro que aponta para o elemento da matriz. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 24 Dimensionando Matrizes em Tempo de Execução ■ A determinação do tamanho de uma matriz pode ser feita em tempo de execução. ■ Para isso deve-se declarar um ponteiro ao invés de uma matriz explícita. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 25 Dimensionando Matrizes em Tempo de Execução - Exemplo /*ProgC050 - Programa que mostra vetor com alocação dinâmica 25/11/2008 - Fabiana Costa Guedes */ #include <iostream> int main(){ int *M, nElem; std::cout << "\nQual a quantidade de elementos: "; std::cin >> nElem; M = new int[nElem]; for (int i=0; i<nElem; i++){ std::cout << "\nDigite o elemento " << i+1 << ": "; std::cin >> M[i]; } delete [] M; system("pause"); return 0; } Declaração de um ponteiro de inteiros. Declaração de um vetor. O tamanho do vetor é colocado em tempo de execução, utilizando para isto o ponteiro. Daí em diante trata normalmente. Na desalocação de memória deve apresentar [] antes do nome do ponteiro, sem colocar o tamanho. 26 Array de Ponteiros ■ Arrays de ponteiros são arrays cujos elementos são ponteiros. ■ Um uso muito comum de arrays de ponteiros são os arrays de strings. ■ No próximo programa é apresentado um array de strings que armazena os dias da semana. ■ Na declaração da variável diaSemana, a parte diaSemana[7] indica que é um vetor de 7 elementos. ■ A parte char * indica que cada elemento do vetor é do tipo "ponteiro para caracter". 27 Array de Ponteiros #include <iostream> int main() { char *diaSemana[7] = {"Domingo", "Segunda-feira", "Terca- feira","Quarta-feira", "Quinta-feira", "Sexta-feira","Sabado"}; int i; for(i=0; i<7; i++) std::cout << diaSemana[i] << "\n"; return 0; } 28 Array de Ponteiros BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 29 Ponteiros void ■ Quando se deseja atribuir um endereço a um ponteiro, este deve ser do mesmo tipo do ponteiro. Entretanto, há uma exceção. ■ Há um tipo de ponteiro de propósito geral que pode apontar para qualquer tipo de dado. ■ Este ponteiro deve ser do tipo void e é declarado por meio da seguinte instrução: void *ptr; ■ Ponteiros void são utilizados em situações onde uma função retorna um ponteiro genérico, ou seja, independente do tipo de dado apontado. ■ Qualquer endereço pode ser atribuído a um ponteiro void. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 30 Ponteiros void - Exemplo /*ProgC055 - Programa que utiliza ponteiro do tipo void 26/11/2008 - Fabiana e Sandro */ #include <iostream> int main() { int i=5; float f=3.2; void *pv; pv = &i; std::cout << *(int *)pv << "\n"; pv = &f; std::cout << *(float *)pv << "\n"; system("pause"); return 0; } Declaração de um ponteiro do tipo void. Recebe o endereço de uma variável inteira. Na hora de apresentar o resultado, deve converter. Recebe o endereço de uma variável float. Conversão automática para float na visualização. 31 Ponteiro - new e delete ■ O comando new é utilizado para obter memória do sistema operacional em tempo de execução. ■ Ele retorna um ponteiro para o início do novo bloco de memória que foi alocado. ■ Uma vez alocada, esta memória continua ocupada até que seja desalocada explicitamente pelo operador delete. 32 Ponteiro - new e delete #include <iostream> int main() { int *intPtr; intPtr = new int(); // aloca memória para 1 inteiro e retorna o endereço // inicial da memória alocada *intPtr = 10; std::cout << *intPtr; delete intPtr; // liberando a memória alocada return 0; } 33 Ponteiro - new e delete #include <iostream> int main() { int *arrayPtr, i, n; std::cin >> n; arrayPtr = new int[n]; for(i=0; i<n; i++) std::cin >> arrayPtr[i]; delete [] arrayPtr; return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 34 Referências para Estruturas ■ Os ponteiros podem apontar para estruturas mais complexas da mesma forma que apontariam para qualquer tipo básico. ■ Para acessar membros de um registro utiliza-se o operador ponto (.). ■ Uma construção análoga, usando somente um ponteiro em vez do nome do objeto, não pode ser utilizada para acessar diretamente os membros da estrutura, pois o operador ponto requer o nome de uma variável (ou objeto) à sua esquerda. Aluno.Nota = 10; BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 35 Referências para Estruturas ■ C++ oferece dois métodos para resolver este problema: o primeiro, menos elegante, é obter a variável apontada por um ponteiro por meio do operador indireto (*): (*Aluno).Nota = 10; // OK ■ Entretanto, esta expressão é de visualização complexa por causa dos parênteses. ■ Os parênteses são necessários, pois o operador ponto tem precedência maior que o operador (*). ■ O segundo método, de uso mais comum, é por meio do operador de acesso a membros (->) que consiste no sinal de menos seguido do sinal de maior que . Aluno->Nota = 10; // OK BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 36 Referências para Estruturas - Exemplo /*ProgC056 - Programa que exemplifica a utilização de ponteiro de registros 26/11/2008 - Fabiana e Sandro*/ #include <iostream> // para entrada e saída struct Venda { int nPecas; float Preco; }; int main() { Venda *V; V = new Venda; std::cout << "\nQuantidade de pecas: "; std::cin >> V->nPecas; std::cout << "\nPreco..............: "; std::cin >> V->Preco; std::cout << "\nQuantidade de pecas = " << (*V).nPecas << "\nPreco............. = " << (*V).Preco << "\n"; system("pause"); return 0; } Declaração estrutura Venda Declaração de ponteiro para estrutura. Utilização do ponteiro.Utilização do ponteiro – outra forma. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 37 Referências para Estruturas - Exemplo #include<cstdio> #include<iostream> using namespace std; struct Aluno { int matricula; char nome[40]; }; void leia_aluno (Aluno *a) { cout << "Matricula: "; cin >> a- >matricula; cin.ignore(); cout << "Nome.....: "; gets(a- >nome); } void imprime_aluno (Aluno *a) { cout << "Matricula digitada: " << a->matricula << endl; cout << "Nome digitado.....: " << a->nome << endl; } int main() { Aluno *student = new Aluno(); leia_aluno (student); imprime_aluno (student); delete student; return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 38 Referências para Estruturas - Exemplo #include<iostream> using namespace std; const int MAX = 5; struct Aluno { int matricula; char nome[40]; }; int main() { Aluno *students = new Aluno[MAX]; for (int i = 0; i < MAX; i++) { cout << "Matricula: "; cin >> students[i].matricula; cin.ignore(); cout << "Nome.....: "; cin.getline (students[i].nome, 40); } for (int i = 0; i < MAX; i++) { cout << "\nMatricula digitada: " << students[i].matricula << endl; cout << "Nome digitado.....: " << students[i].nome << endl; } delete [] students; return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 39 Referências para Estruturas - Exemplo #include<iostream> using namespace std; const int MAX = 5; struct Aluno { int matricula; char nome[40]; }; void leia_aluno (Aluno *a) { cout << "Matricula: "; cin >> a->matricula; cin.ignore(); cout << "Nome.....: "; cin.getline (a- >nome, 40); cout << endl; } void imprime_aluno (Aluno *a) { cout << "\nMatricula digitada: " << a- >matricula << endl; cout << "Nome digitado.....: " << a->nome << endl; } int main() { Aluno *students = new Aluno[MAX]; for (int i = 0; i < MAX; i++) { leia_aluno(&students[i]); } for (int i = 0; i < MAX; i++) { imprime_aluno(&students[i]); } delete [] students; return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 40 Referências para Estruturas - Exemplo #include<iostream> using namespace std; const int MAX = 5; struct Aluno { int matricula; char nome[40]; }; void leia_alunos (Aluno **alunos) { for(int i=0; i<MAX; i++) { cout << "Matricula: "; cin >> (*alunos)[i].matricula; cin.ignore(); cout << "Nome.....: "; cin.getline ((*alunos)[i].nome, 40); cout << endl; } } void imprime_alunos (Aluno **alunos) { for(int i=0; i<MAX; i++) { cout << "\nMatricula digitada: " << (*alunos)[i].matricula << endl; cout << "Nome digitado.....: " << (*alunos)[i].nome << endl; } } int main() { Aluno *students = new Aluno[MAX]; leia_alunos(&students); imprime_alunos(&students); delete [] students; return 0; } BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 41 Exercícios ■ Escreva uma função que inverta a ordem dos caracteres de uma cadeia de caracteres que ela recebe como argumento. Use ponteiros. ■ Escreva um programa que solicite ao usuário o número de notas a serem digitadas, crie um vetor, com a dimensão especificada, para armazenar as entradas, solicite as notas e chame uma função que retorne a média aritmética das notas. Após imprimir a média, o programa libera a memória alocada para o vetor. Use ponteiros. BAC004 - Informática - Aulas Teóricas - Fabiana Costa Guedes 42 Exercícios ■ Crie uma estrutura para descrever restaurantes. Os membros devem armazenar o nome, o endereço, o preço médio e o tipo de comida. Leia um item e depois apresente-o na tela. Utilize ponteiros.
Compartilhar