Baixe o app para aproveitar ainda mais
Prévia do material em texto
FUNDAÇÃO UNIVERSIDADE FEDERAL DO VALE DO SÃO FRANCISCO UNIVASF Ponteiros em C: um resumo básico Igor França Engenharia de Computação Juazeiro, BA Julho de 2013 Fundação Universidade Federal do Vale do São Francisco 3 PONTEIROS 1 Definição Ponteiros são variáveis — assim como int, char etc — que contêm endereços de memória — normalmente a posição de outra variável de mesmo tipo. 2 Declaração tipo *nome; A variável nome irá conter um ponteiro de tipo base tipo. A variável só poderá designar para outras de seu mesmo tipo, de acordo com a aritmética de ponteiros¹. A imagem a seguir ilustra o uso de uma variável ponteiro Figura 1: variável apontando para outra 3 Operadores Há duas operações básicas de ponteiros: * e &. O & devolve o endereço na memória de seu operando. Por exemplo x = &example; Põe, em x, o endereço de memória da variável que contém example. Então, se example está na posição 81 de memória e tem valor 10, x terá o valor 81. Já o operador * funciona para devolver o valor da variável localizada no endereço que ele aponta. Daí y = *x; Ponteiros em C 4 Logo, y receberá o valor 10, porque é o valor que está armazenado na posição 81, que x armazenava. 4 Indireção Múltipla Pode-se ter um ponteiro apontando para outro ponteiro que aponta para o valor final. Vale ressaltar que indireção múltipla difere de lista ligada², pois são conceitos diferentes. A indireção múltipla pode ser levada a qualquer nível, porém, é complexa de seguir e sujeita a erros. Dificilmente é necessário uso de várias indireções. Para se declarar uma variável ponteiro para ponteiro deve ser declarada usando-se mais um * a frente do nome da variável, ou seja: tipo **nome; Ou seja, a variável nome de como tipo básico tipo irá apontar para um ponteiro de ponteiro de mesmo tipo básico. Exemplo 1. float x 2. float *p; 3. float **q; 4. 5. x = 10.0; 6. p = &x; 7. q = &p; 8. 9. printf(“&p = %d = p = %d”, &p, q); 10.printf(“**p = %f = x = %f”, **p, x); No código acima, primeiramente, após as declarações, são feitas as atribuições de valores: x recebe 10.0 (float), p recebe o endereço de x e q recebe o endereço para que p aponta. Na tela será possível verificar que o endereço de p é igual à variável q – ponteiro para ponteiro, e que x tem o mesmo valor que q. 5 Ponteiros para Funções Quando cada função é compilada, é criado um código-objeto a partir do código-fonte, e um é estabelecido um ponto de entrada. No momento que a função é chamada, é efetuada uma chamada ao ponto de entrada, ao tempo que o programa é executado. Logo, se um ponteiro contém esse valor de entrada da função, ele pode ser utilizado para chamar a função. Analise o código a seguir para melhor entendimento 1. #include <stdio.h> 2. #include <stdlib.h> 3. #include <string.h> 4. //-------------------------------------------------------------------------- 5. void checar(char *a, char *b, int (*cmp)(const char *, const char *)); Fundação Universidade Federal do Vale do São Francisco 5 6. //-------------------------------------------------------------------------- 7. void main() 8. { 9. char x1[80], x2[80]; 10. int (*p)(); 11. 12. p = strcmp; // strcmp() é a função da biblioteca string.h 13. // que compara dois strings 14. gets(x1, x2); 15. checar(x1, x2, p); 16. } 17. //-------------------------------------------------------------------------- 18. void checar(char *a, char *b, int (*cmp)(const char *, const char *)) 19. { 20. printf("testando igualdade"); 21. 22. if(!(*cmp)(a, b)) printf("strings iguais"); 23. else printf("strings diferentes"); 24. } É necessário o uso de parênteses em (*cmp) para o entendimento do termo como função, do compilador. 6 Alocação Dinâmica Para o uso de alocação de memória em tempo de execução, quando a quantidade de espaço utilizado é desconhecida, é necessário que o programa efetue funções de operações dinâmicas, e aí onde entram as funções de alocação dinâmica. A memória de alocação é obtida do heap da máquina, e é desconhecido seu real tamanho. As principais funções para alocação em C são malloc( ) e free( ). Enquanto malloc() cria um espaço de memória para armazenamento dos parâmetros do código, free( ) libera. Para o uso dessas funções é necessário o uso da biblioteca stdlib.h. A declaração de malloc( ) é da forma void *malloc(size_t num_de_bytes); A função devolverá um ponteiro de tipo void, que assim, será possível ser utilizada qualquer espécie de ponteiro. Demos como exemplo 1. char *p; 2. p = malloc(100); Ponteiros em C 6 Logo, p apontará para os primeiros 100 bytes de memória livre. Ainda é possível usar sizeof para garantir a portabilidade 1. int *p; 2. p = malloc(10*sizeof(int)); Já a função free( ) pode ser usada, a partir da alocação de malloc( ), em uma declaração geral void free(void *p); Onde p é o ponteiro para a memória alocada anteriormente. Dado isso, podemos exemplificar com um código, tratando das duas funções: primeiramente, será alocado um valor, e, em seguida, ele será liberado. Segue 1. #include <stdlib.h> 2. #include <stdio.h> 3. #define X 10 4. //--------------------------------------------------- 5. void alocar(int *p); 6. void liberar(int *p); 7. //--------------------------------------------------- 8. int main() 9. { 10. int *p; 11. 12. alocar(p); 13. liberar(p); 14. return 0; 15. } 16. //--------------------------------------------------- 17. void alocar(int *p) 18. { 19. p = malloc(sizeof(X)); 20. 21. if(p == NULL) printf("sem memoria\n"); 22. else printf("alocado\n"); 23. } 24. //--------------------------------------------------- 25. void liberar(int *p) 26. { 27. if(p != NULL) { 28. free(p); 29. printf("liberado\n"); 30. } 31. } Fundação Universidade Federal do Vale do São Francisco 7 6 Problemas com Ponteiros A medida que os ponteiros são de grande atribuição na linguagem, sua valia é imensa. Mas há problemas que comumente acontecem. O principal é o ponteiro selvagem. Quando não se é iniciado um ponteiro, ao iniciar a execução no programa, pode haver uma referenciação com uma variável contendo lixo. Isso pode ser imperceptível. É aí que está o problema: encontrar um erro em um ponteiro, sendo que talvez nem seja ele, em si, o erro, e sim, a forma que foi inicializada – ou não. Analise o código a seguir 1. #include <stdio.h> 2. #include <stdlib.h> 3. //--------------------------------------------------- 4. int main() 5. { 6. char *p; 7. char s[50]; 8. 9. p = s; 10. do{ 11. gets(s); 12. while(*p) printf(" %i", *p++); // imprime o valor ASCII para 13. // cada caractere 14. } while(strcmp(s, "done")); 15. } Nesse programa, p é utilizado para apresentar os valores ASCII para cada letra da palavra de entrada. Mas há um erro: p recebe somente o primeiro valor de s, logo, após o primeiro laço, serão apresentados valores quaisquer, já contidos em memória.Ponteiros em C 8 REFERENCIAÇÃO ¹ Em ponteiros só podem ser feitas somas e subtrações; ² Para maiores informações sobre lista ligada, consulte o livro CORMEN, Thomas H.. Algoritmos: teoria e prática. Rio de Janeiro: Campus, 2002 e os endereços: http://pt.wikipedia.org/wiki/Lista_ligada http://www.ime.usp.br/~pf/algoritmos/aulas/lista.html http://www.lis.ic.unicamp.br/~mc102/files/lista-ligada-exercicio.pdf BIBLIOGRAFIA SCHILDT, Herbert. C Completo e Total. 3 ed. São Paulo, Pearson Makron Books. http://www.cplusplus.com/
Compartilhar