170 likes | 308 Views
Aula prática 8 Ponteiros Monitoria de Introdução à Programação. Roteiro. Ponteiros Definição. Operadores. Ponteiros e Variáveis. Ponteiros e Vetores. Ponteiros e Funções. Duvidas Exercícios. Ponteiros - Definição.
E N D
Aula prática 8 Ponteiros Monitoria de Introdução à Programação
Roteiro • Ponteiros • Definição. • Operadores. • Ponteiros e Variáveis. • Ponteiros e Vetores. • Ponteiros e Funções. • Duvidas • Exercícios
Ponteiros - Definição • Ponteirossãotipos de dados quereferenciam (ou “apontam” para) • endereçosde memória. • Emalgumaslinguagens com maiorabstração, ponteirosnãoexistem • expostosaoprogramador (comoem Java) ou tem alternativasmaisseguras • emoutros tipos de dados (como o tipo “referência” em C++). • Acessar o valor nesseendereço é chamado de “dereferenciar” o ponteiro. • Em C, um ponteiro é um numerointeiro, referindo-se aoendereçona • memória.
Ponteiros - Declaração • A sintaxeparadeclarar um ponteiro, é, em C: tipo *nome; outipo* nome; Para declararponteirosemumamesmalinhadeve-se usar o * para cadaponteiro: tipo *pont1, *pont2, var, *pont3; Como qualquer outro tipo, podemostervetores de ponteiros: tipo *vetorDePonteiros[tamanho]; • E, como um ponteiro é um tipo, podemosterponteirosparaponteiros • (ad infinitum): tipo **ponteiroDePonteiroDeTipo; tipo ***ponteiroDePonteiroDePonteiroDeTipo;
Ponteiros - Operadores - & • Para a atribuição de valoresparaponteiros, usamos o operador “=“, • comofizemos com qualquer outro tipo, MAS: • Emgeralnão se atribuemvaloresarbitráriosaosponteirospoisraramente • usa-se endereçosquesãoconstantes* paratodas as execuções do programa. • Emvez disso utiliza-se o operador& para se obter o endereço de variáveis. • Exemplo: intvar; int* ponteiro; ponteiro = &var; //ponteirorecebe o endereço de var *: Exceçãopara o endereço NULL, queequivaleaoendereço 0, normalmenteretornado porfunçõesemcaso de erro, ouparaindicarque o ponteironãoapontaparalugarnenhum.
Ponteiros - Operadores - * • Mas somente obter o endereço não é o bastante. É preciso também poder acessar o conteúdo de endereços. Para isso é utilizado o operador * (dereferenciador): int var = 5; int* pont = &var; //Guarda o endereço de var printf(“%d”, *pont); /* Imprime o conteúdo do endereço guardado por pont, isto é, 5 */ Podemos também usar a notação de vetores para acessar o conteúdo de um ponteiro (pois vetores são como ponteiros): int vetorInt[6]; int* pvetor = vetorInt; //Recebe o endereço inicial do vetor int inteiro = pvetor[5]; O que é equivalente a: inteiro = *(pvetor + 5);
Ponteiros - Cuidados • Porém, aoacessar o conteúdo de um ponteiro, devemostercuidado: • um ponteiro com um endereço de memóriainválidoounulo, aoser • dereferenciado, irácausar um erro de “Falha de segmentação” • (segmentation fault), finalizandoforçadamente a execução de seuprograma. • Coisasdessetipodevemserevitadas: double* pont; //Ponteironãoinicializado (possuilixo de memória) *pont = 2.5; //Altera conteúdo de endereçoqualquer long* pLong; intinteiro = *pLong; //Recebeconteúdo de endereçoqualquer char* string = NULL; puts(string); //Tentaalterarconteúdo do endereço NULL
Ponteiros - Aritmética • Podemosusar as operações de adição e subtração com ponteiros. • Issopermitecoisasdessetipo: pInt=(pVetor+5); pVetor++; pVetor--; pChar-=3; • Multiplicação e divisãonãosãosuportadas, nem soma de doisponteiros, • poisissonãofazsentido se tratando de memória. • As operações de adição, subtração, incremento e decremento se dãoem • funçãodo tamanho do tipopara o qual o ponteiroaponta. Se tivermos um • ponteiroparainteiro e incrementarmosesseponteiropor um, eleapontará • parao endereço de memória 4 bytes adiante.
Ponteiros e Variáveis – Acesso Indireto • Podemos, usandoosoperadoresapresentados, fazer um ponteiroapontar • paraum endereço de umavariável e com issoalterar, se quisermos, o • valor dessavariávelindiretamente. floatvar = 2.0; float* pfloat = &var; //pfloatapontaparavar *pfloat = 12.0; //Equivale a 'var = 12.0;'
Ponteiros - Vetores • Entãopodemospensar, corretamente, queaodeclararumavariável da forma float *pFloat; Estamosdeclarandoque o conteúdoaoqualpFloataponta é do tipo float, tornandopFloat um ponteiropara float. • Porisso, a seguintedeclaraçãotambém é válida: char (*pString)[50]; Declarandoque o conteúdoaoqualpStringaponta é do tipovetor de char de 50 posições, tornandopString um ponteiroparavetor de char de 50 posições. • Como estamosdeclarando um ponteiro, e não a variávelemsi, memória • nãoé reservadaparaessavariável, queinicialmenteapontapara um • endereçoqualquernamemória.
Ponteiros - Vetores • Como jáfoidito, ponteirosguardamendereços. Vetorestambém. • Portantopodemosacessarosvalores do vetorusandoponteiros. char string[20]; char* pchar= string; • Para acessarcadaelemento: for(i=0;i<20;i++) { //Notação de vetor aux =pchar[i]; //Notação de ponteiro *(pchar+i) =funcao(); }
Ponteiros - Matrizes • Porém, paraacessarmatrizesatravés de ponteiros, temosquetercuidado: Uma matriz é um espaçocontínuonamemória, sendoacessado diferenciandosomente um endereço: intmatriz[20][10]; matriz[i][j];//isso *(matriz+i*10+ j);//Equivale a isso Pode-se tambémolhar a matrizcomo um vetor de vetores e portanto acessá-la usandoponteiro de ponteiro: matriz[i][j];//Isso *( *(matriz+i) + j);//Equivale a isso
Ponteiros - Passagem por referência • Ponteiros, porseremendereços, permitemqueacessemos e • modifiquemosdados externos à função, de dentro da função, • contornandoa passagem de variáveisporcópia*: voidfuncao(int* pont) { *pont = 5; /* A funçãoirámodificar o conteúdo do endereço passadocomoparâmetro */ } int main() { intvar = 4; funcao(&var); //Passo o endereço de 'var' comoparâmetro printf(“%d”, var); //E portanto o valor impressoserá 5 return 0; } *: A passagemainda é porcópia, mas o valor copiado é o endereço.
Ponteiros - Passagem por referência • Podemos, dessa forma, “retornar” mais de um valor porexecução de função. • Isso é muitoútilquando é preferívelretornar o estado da execuçãoda • função, como um código de erroou de execuçãocorreta:
Exercício 1 Interferência! Um matemáticoestavaavaliando um fenômeno e percebeu um comportamentoestranho no seusinal. Eletentavaproduzir um sistemacrescente, mas percebeuqueocorriamoscilaçõesbruscas de sinal. Elepercebeuque a função do tempo querege o sinal é: se t é divisívelpor 3 , se t é divisívelpor 2 e nãopor 3 , se t não for divisívelpor 2 nempor 3. Faça um programaquereceba do usuário um inteiro ‘t’ e queuse umafunção void quereceba um ponteirodesseinteiro, paraque estesejamodificado e no final sejaprintado o resultado de f(t). Exs.: f(6) = 2; f(7) = 3; f(8) = 77844992; f(9) = 3, f(10) = 711312970
Exercício 2 • Faça um programaquereceba um vetor de até 20 inteiros e o inverta • trocandoosseuselementosseguindo a ordem: • O últimoelemento com o primeiro, o segundo com o penúltimo, • o terceiro com o antepenúltimo... • Exemplo: • Entrada: 5 valores 1 5 8 9 10 • Saída: 10 9 8 5 1 • Obs: • Deveserfeitaumafunção void swap para trocar oselementos • e deve-se acessar o vetorusandonotação de ponteiros