Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Prof Ms. Eng Elaine Ceclia Gatto Curso de Bacharelado em Engenharia de Computao Universidade do Sagrado CoraO USC Bauru/SP
Introduo
Ponteiros esto entre as capacidades mais difcieis de se dominar na linguagem C; Ponteiros permitem: Simular uma chamada por referncia; Criar e manipular estruturas dinmicas de dados; Estruturas de dados podem crescer e encolher no tempo de execuo; Listas interligadas, filas, pilhas, rvores, etc., so exemplos de estruturas de dados dinmicas; Ponteiros so variveis cujos valores so endereos de memria; Uma varivel comum contm claramente um valor especfico;
Introduo
Ponteiros so utilizados em situaes em que o uso do nome de uma varivel no permitido ou indesejvel; Ponteiros fornecem maneiras com as quais as funes podem realmente modificar os argumentos que recebem passagem por referncia; Ponteiros passam matrizes e strings mais convenientemente de uma funo para outra; Ponteiros manipulam os elementos de matrizes mais facilmente, por meio da movimentao de ponteiros para elas ou parte delas no lugar de ndices entre colchetes;
Introduo
Ponteiros alocam e desalocam memria dinamicamente no sistema; Ponteiros passam para uma funo o endereo de outra funo. Um ponteiro um tipo especial de varivel que foi concebida para conter o endereo de outra varivel; Um ponteiro armazena um endereo de memria, que a localizao de outra varivel; Uma varivel aponta para outra varivel quando a primeira contm o endereo da segunda;
Introduo
A memria do computador dividida em bytes, numerados de zero at o limite da memria do computador; Esses nmeros so chamados de endereos de bytes; Um endereo uma referencia que o computador usa para localizar variveis; Seu endereo o do primeiro byte ocupado por ela; Os programas, quando carregados, ocupam uma certa parte da memria; Toda varivel e toda funo dos programas em C comeam em um endereo particular, que chamado endereo da varivel ou da funo;
Introduo
Um ponteiro, diferentemente de uma varivel comum, contm um endereo de uma varivel que contm um valor especfico; Uma varivel comum referencia um valor diretamente; Um ponteiro referencia um valor indiretamente; INDIREO: a referncia de valor por meio de um ponteiro; Ponteiros devem ser definidos antes de sua utilizao, como qualquer outra varivel; Exemplo: int *countPtr, count; O que faz esse linha de cdigo? Pense!
Introduo
A linha acima pode ser reescrita da seguinte forma: int *countPrt; int count; Note que foram criadas duas variveis do tipo INT, entretanto, uma delas um ponteiro; Todo ponteiro necessita do smbolo * antes do nome da varivel; Portanto, int *countPtr especifica que a varivel countPtr do tipo int * - um ponteiro para um inteiro, e pode ser lido de duas formas: countPtr um ponteiro para int; countPtr aponta para um objeto do tipo int;
Introduo
A varivel count definida para ser um inteiro, e no um ponteiro para int; Se quisermos que count seja um ponteiro, devemos alterar a declarao int count para int *count;
count 7 countPtr count 7
Introduo
Cuidado: A notao *, usada para declarar variveis de ponteiro, no distribui para todos os nomes de variveis em uma declarao; Cada ponteiro precisa ser declarado com o * prefixado ao nome; Exemplo: se voc quiser declarar xPtr e yPtr como ponteiros int, ento use int *xPtr, *yPtr; Dica; Inclua as letras Ptr nos nomes de variveis de ponteiros para deixar claro que essas variveis so ponteiros, e, portanto, precisam ser tratadas de modo apropriado; Inicialize os ponteiros para evitar resultados inesperados;
Introduo
Ponteiros devem ser inicializados quando so definidios ou ento em uma instruo de atribuio; Ponteiros podem ser inicializados com NULL, zero, ou um endereo; NULL: no aponta para nada, uma constante simblica; Inicilizar um ponteiro com zero o mesmo que inicializar com NULL; Nesse caso zero convertido em um ponteiro apropriado; Zero o nico valor inteiro que pode ser atribud diretamente a um ponteiro. int *xPtr = NULL; int *yPtr = 0;
Introduo
Exemplo: para conhecer o endereo ocupado por uma varivel usamos o operador de endereos &. O resultado da operao um ponteiro constante. #include <stdio.h> #include <stdlib.h> int main(){ int i, j, k; printf(Endereo de i = %p \n, &i); printf(Endereo de j = %p \n, &j); printf(Endereo de k = %p \n, &k); system(Pause); return 0; }
Operadores de Ponteiros
& = operador de endereo = um operador unrio que retorna o endereo de seu operando; Exemplo: int y = 5; int *yPtr; yPtr = &y A terceira instruo atribui o endereo da varivel y varivel de ponteiro yPtr; A varivel yPtr aponta para y;
Operadores de Ponteiros
yPtr y 5
60.000
Operadores de Ponteiros
O operador unrio *, retorna o valor do objeto apontado por seu operando; O operardor indireto * unrio e opera sobre um endereo ou ponteiro; O resultado da operao o nome da varivel localizada nesse endereo apontada; O nome da varivel representa o seu valor ou contedo; Por fim, resulta o valor da varivel apontada; Exemplo: printf(%d, *yPtr); Imprime o valor da varivel y; O uso de * chamado de desreferenciao de um ponteiro;
Operadores de Ponteiros
O operador de endereos & opera sobre o nome de uma varivel e resulta o seu endereo, j o operador indireto * opera sobre o endereo de uma varivel e resulta o seu nome. Dica: Acessar um contedo com um ponteiro que no foi devidamente inicializado ou que no foi designado para apontar um local especfico na memria um erro. Isso poderia causar um erro fatal no temp de execuo, ou poderia acidentalmente modificar dados e permitir que o programa fosse executado at o fim com resultados incorretos;
Operadores de Ponteiros
Exemplo: o cdigo a seguir demonstra a utilizao dos operadores & e *. %p mostra o local da memria como um inteiro hexadecimal na maioria das plataformas. #include <stdio.h> #include <stdlib.h> int main(){ int a; int *aPtr; a = 7; aPtr = &a; printf("Endereco de a = %p \n", &a); printf("O valor de aPtr = %p \n", aPtr); printf("O valor de a = %d \n", a); printf("O valor de aPtr = %d \n", *aPtr); printf("* e & sao complementos um do outro: \n"); printf("&*aPtr = %p \n", &*aPtr); printf("*&aPtr = %p \n", *&aPtr); system("Pause"); return 0; }
Operadores de Ponteiros
aPtr
#include <stdio.h> 0022FF44 0022FF44 7 #include <stdlib.h> int main(){ Nesta parte do programa, as variveis esto sendo int a; declaradas e inicializadas. A varivel a do tipo int int *aPtr; recebe o valor 7. O ponteiro para um inteiro, aPtr, a = 7; recebe o endereo da varivel a, que do tipo int. aPtr = &a; printf("Endereco de a = %p \n", &a); printf("O valor de aPtr = %p \n", aPtr); printf("O valor de a = %d \n", a); printf("O valor de aPtr = %d \n", *aPtr); printf("* e & sao complementos um do outro: \n"); printf("&*aPtr = %p \n", &*aPtr); printf("*&aPtr = %p \n", *&aPtr); system("Pause"); return 0; }
Operadores de Ponteiros
aPtr a
#include <stdio.h> 0022FF44 0022FF45 7 #include <stdlib.h> int main(){ int a; int *aPtr; Imprimindo o local da memria da a = 7; varivel int a como um inteiro aPtr = &a; hexadecimal. Observe que o valor do printf("Endereco de a = %p \n", &a); ponteiro aPtr o endereo da varivel printf(Valor de aPtr = %p \n", aPtr); int a. printf(Valor de a = %d \n", a); printf(Valor de aPtr = %d \n", *aPtr); printf("* e & sao complementos um do outro: \n"); printf("&*aPtr = %p \n", &*aPtr); printf("*&aPtr = %p \n", *&aPtr); system("Pause"); return 0; }
Operadores de Ponteiros
aPtr a
#include <stdio.h> 0022FF44 0022FF45 7 #include <stdlib.h> int main(){ int a; int *aPtr; Imprimindo os valores da varivel int a e a = 7; do ponteiro para um inteiro aPtr. Observe aPtr = &a; que aqui utiliza-se %d e no %p. Note printf("Endereco de a = %p \n", &a); que aqui estamos usando *aPtr e no printf(Valor de aPtr = %p \n", aPtr); apenas aPtr. Tambm na varivel a, usaprintf(Valor de a = %d \n", a); se apenas a e no &a. printf(Valor de aPtr = %d \n", *aPtr); printf("* e & sao complementos um do outro: \n"); printf("&*aPtr = %p \n", &*aPtr); printf("*&aPtr = %p \n", *&aPtr); system("Pause"); return 0; }
Operadores de Ponteiros
aPtr a
#include <stdio.h> 0022FF44 0022FF44 7 #include <stdlib.h> int main(){ int a; int *aPtr; a = 7; aPtr = &a; printf("Endereco de a = %p \n", &a); printf(Valor de aPtr = %p \n", aPtr); printf(Valor de a = %d \n", a); printf(Valor de aPtr = %d \n", *aPtr); printf("* e & sao complementos um do outro: \n"); printf("&*aPtr = %p \n", &*aPtr); Quando os dois operadores so printf("*&aPtr = %p \n", *&aPtr); aplicados consecutivamente varivel aPtr em qualquer system("Pause"); ordem,ento os operadores & e * return 0; so complementos um do outro }
?: = += -= *= /= %=
,
Condicional Atribuio
Vrgula
int a[5]; aPtr = v; aPtr = &a[0]; aPtr += 2; Suponho que o primeiro elemento esteja no local 3000 e que o inteiro esteja armazenado em 4 bytes da memria, o resultado de aPtr+=2 ser 3008 pois (3000 + 2 * 4) = 3008. Se o inteiro estiver armazenado em 2 bytes da memria, ento o resultado ser 3004, pois (3000 + 2 * 2) = 3004.
Local na memria
Aps a soma
Ponteiro Void
Um ponteiro pode ser atribudo a outro se ambos forem do mesmo tipo, exceto quando o ponteiro for um ponteiro para void; Exemplo: no podemos atribuir um endereo de uma varivel int a um ponteiro float; Um ponteiro para void um ponteiro genrico que pode representar qualquer tipo de ponteiro; Todos os tipos de ponteiro podem receber um ponteiro para void, e este pode receber um ponteiro de qualquer tipo; Um ponteiro para void no pode ser desreferenciado; Um ponteiro para int refere-se a 4 bytes de memria em uma mquina com inteiros de 4 bytes;
Ponteiro Void
O compilador ento sabe quanto de espao reservar para um ponteiro do tipo int; Mas o compilador no sabe quanto de espao reservar, na memria, para um tipo void; Um ponteiro para void simplesmente contm um local da memria para um tipo de dado desconhecido; O nmero exato de bytes aos quais o ponteiro se refere no conhecido pelo compilador; Um ponteiro void um ponteiro de propsito geral; Atribuir um ponteiro de um tipo a um ponteiro de outro tipo se nenhum deles for do tipo void * consistem em um erro de sintaxe;
Ponteiro Void
So usados em situaes em que seja necessrio que uma funo receba ou retorne um ponteiro genrico e opere independentemente do tipo de dado apontado; Qualquer endereo pode ser atribudo a um ponteiro void; void *p; O contedo da varivel de um ponteiro void no pode ser acessado por meio desse ponteiro; Para isso necessrio criar outro ponteiro e fazer a converso de tipo na atribuio; Exemplo:
Ponteiro Void
#include <stdio.h> #include <stdlib.h> int main(){ int i=5, *pi; float f=3.2, *pf; void *pv; pv = &i; pi=(int *)pv; //CONVERSO printf("\n *pi = %d \n ", *pi); pv = &f; pf =(float *)pv; //CONVERSO printf("\n *pf = %3.2f \n \n", *pf); system("PAUSE"); return 0; }