[CAPÍTULO 1] - [CAPÍTULO 2] - [CAPÍTULO 3]
[PARTE 1] - [PARTE 2] - [PARTE 3] - [PARTE 4] - [PARTE 5] - [PARTE 6] - [PARTE 7]
[PARTE 1] - [PARTE 2] - [PARTE 3] - [PARTE 4] - [PARTE 5] - [PARTE 6] - [PARTE 7]
Ponteiros
Conceito
Um PONTEIRO ou APONTADOR é uma variável usada para armazenar um endereço de memória.Normalmente, o endereço armazenado em um PONTEIRO é a posição de uma outra variável na memória. Se uma variável contém o endereço e uma outra, então a primeira variável é dita apontar para a segunda.
Declaração
De maneira geral, uma variável ponteiro de nomeID
é declarada assim:ESPECIFICADORES * ID = INICIALIZADOR;onde, o
= INICIALIZADOR
é opcional (como em toda declaração de variável).Operadores de Ponteiros
Existem dois operadores especiais para ponteiros: o*
e o &
.Operador &
Um operador unário que devolve o endereço na memória do seu operando.int m; int * p; p = &m; /* p recebe o endereço onde se localiza a var. m */ ...
Operador *
É o complemento de&
. Quer dizer, devolve a variável localizada no endereço armazenado em um apontador.p = &m; m = 3; printf("%p", p); /* imprime o endereço de m */ printf("%d", *p); /* imprime 3 que é o conteúdo de m */ ...
Ponteiros e Arranjos
Há uma estreita relação entre PONTEIROS e ARRANJOS (vetores, matrizes e strings).O nome de um ARRANJO (vetor, matriz ou string) é sempre um PONTEIRO para o primeiro elemento do ARRANJO.
char str[80], *pstr; pstr = str; /* pstr aponta para str[0] */
Assim, a décima posição de um ARRANJO (vetor, matriz ou string) pode ser acessada de duas maneiras:
pstr = str; /* pstr aponta para str[0] */ printf("%c", str[9] ); /* imprime o 10o elemento de str */ printf("%c",*(pstr + 9)); /* imprime o 10o elemento de str */
Aritmética de Ponteiros
Existem apenas duas operações aritméticas que podem ser usadas com ponteiros: adição e subtração.Cada vez que um ponteiro é incrementado, ele aponta para a posição de memória do próximo elementodo seu tipo base.
Cada vez que um ponteiro é decrementado, ele aponta para a posição de memória do elemento anterior.
Aplicações
O correto entendimento e uso de ponteiros é crítico para uma programação bem-sucedida em C. Há pelo menos três razões para isto:- ponteiros fornecem os meios pelos quais as funções podem modificar seus argumentos
- formam a base para a alocação dinâmica (variáveis no heap)
- aumenta a eficiência de certas rotinas
De agora em diante, até o final do curso, iremos explorar em variados graus de detalhes o conceito básico de ponteiros.
Atividade 1
Aplicando os conhecimentos adquiridos na última aula e nesta, iremos agora implementar uma primeira versão de uma lista de strings.Dado o código abaixo (que pode ser obtido como projeto Dev-Cpp neste link), complemente o código do arquivo
lista.c
escrevendo as funções:-
list_rem()
-
list_get()
-
list_set()
main.c
/* main.c **/ #include <stdio.h> #include <stdlib.h> #include "list.h" #include "xcpt.h" int main(int argc, char *argv[]) { while (1) { char str[1024]; int pos; const char * xc; printf("\nAdicionar\n"); printf(" pos = "); scanf("%d",&pos); printf(" str = "); gets(str); gets(str); list_add(str,pos); /* TRY(list_add(str,pos)); CATCH(INDEX_OUT_OF_BOUNDS_XCPT,xc) printf("\npos invalida!\n"); CATCH(LIST_FULL_XCPT,xc) printf("\nlista cheia!\n"); CATCH(LINE_TOO_LONG_XCPT,xc) printf("\nstr muito grande!\n"); */ printf("\nLista\n"); list_print(); } }
list.h, list.c
/* list.h, Rev. 1.1 (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br> Implements a list of strings. **/ #ifndef LIST_H #define LIST_H #define LIST_MAX_SIZE 99 #define LINE_MAX_SIZE 60 #define LIST_FULL_XCPT "list full" #define LINE_TOO_LONG_XCPT "line too long" unsigned short list_size(void); void list_add(const char * str, unsigned short pos); char * list_rem(unsigned short pos); void list_set(const char * str, unsigned short pos); char * list_get(unsigned short pos); void list_print(void); #endif
/* list.c, Rev. 1.1 (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br> Implements a list of strings. **/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "list.h" #include "xcpt.h" /** private data */ static char list[LIST_MAX_SIZE][LINE_MAX_SIZE+1]; static unsigned short size = 0; static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE+1]; /** public functions */ unsigned short list_size(void) { return size; } /* Add a new element str in the list at a given position pos. From pos to the end of the list, all existing elements are shifted right. Throws: INDEX_OUT_OF_BOUNDS_XCPT when pos is invalid ( > size +1 ) LIST_FULL_XCPT when the list size equals LIST_MAX_SIZE LINE_TOO_LONG_XCPT when str is greater than LINE_MAX_SIZE **/ void list_add(const char * str, unsigned short pos) { sprintf(xcpt_cmsg,"@%s[%d]\n> list_ins (\"%s\",%d);\n", __FILE__,__LINE__,str,pos); if ( pos > size + 1 ) { THROW(INDEX_OUT_OF_BOUNDS_XCPT,xcpt_cmsg); return ; } if ( size + 1 > LIST_MAX_SIZE ) { THROW(LIST_FULL_XCPT,xcpt_cmsg); return ; } if ( strlen(str) > LINE_MAX_SIZE ) { THROW(LINE_TOO_LONG_XCPT,xcpt_cmsg); } if ( pos == 0 ) { strncpy(list[size],str,LINE_MAX_SIZE); } else { int i; for ( i = size ; i >= pos; i-- ) strcpy(list[i],list[i-1]); strncpy(list[i],str,LINE_MAX_SIZE); } size++; } char * list_rem(unsigned short pos) { } void list_set(const char * str, unsigned short pos) { } char * list_get(unsigned short pos) { } void list_print(void) { int i; for ( i=0; i < size; i++ ) printf("%2d: %s\n",i+1,list[i]); }
xcpt.h, xcpt.c
/* xcpt.h, Rev. 1.1 (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br> Implements an exception handling mechanism inspired in Java. **/ #ifndef XCPT_H #define XCPT_H #define XCPT_NAME_MAX_SIZE 32 #define XCPT_CMSG_MAX_SIZE 1024 #define THROW(e,m) __throw((e),(m)) #define TRY(f) __begin_try();f;__end_try(); #define CATCH(e,m) if(m=__catch(e)) #define NULL_POINTER_XCPT "null pointer" #define INDEX_OUT_OF_BOUNDS_XCPT "index out of bounds" #define OVERFLOW_XCPT "overflow" #define UNDERFLOW_XCPT "underflow" #define ILLEGAL_ARGUMENT_XCPT "illegal argument" void __begin_try(void); void __end_try(void); const char * __catch(const char *name); void __throw(const char *name, const char *cmsg); #endif
/* xcpt.c, Rev. 1.1 (c) 2007, Luciano R. Coutinho <lrc@deinf.ufma.br> Implements an exception handling mechanism inspired in Java. **/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "xcpt.h" static char xcpt_name[XCPT_NAME_MAX_SIZE + 1]; static char xcpt_cmsg[XCPT_CMSG_MAX_SIZE + 1]; static int trying; /* Sets try_flag. **/ void __begin_try(void) { trying = 1; } /* UnSets try_flag. **/ void __end_try(void){ trying = 0; } /* From exception name, gets the exception message thown by __throw(n,m). Once cautch, the exception name is cleared . **/ const char * __catch(const char * name) { if ( strcmp(xcpt_name,name) == 0 ) { xcpt_name[0] = '\0'; return xcpt_cmsg; } else return NULL; } /* Stores an exception contextual message. When called outside a __begin_try(); ...; __end_try(); pair, the exception message is also printed to the stderr stream . **/ void __throw(const char * name,const char * cmsg) { strncpy(xcpt_name,name,XCPT_NAME_MAX_SIZE); strncpy(xcpt_cmsg,cmsg,XCPT_CMSG_MAX_SIZE); if ( !trying ) fprintf(stderr,"exception: %s: %s\n",xcpt_name,xcpt_cmsg); }
Leitura recomendada
- CCT Cap 5
Exercícios
Termine a atividade 1 acima, escrevendo as funções:-
list_rem()
-
list_get()
-
list_set()
Bibliografia e fonte:
- [CCT] Schildt, H. (1996) C, completo e total: 3a Ed.. São Paulo, Makron.
- LP, UFMA; Coutinho, Lucian. Linguagem de programação para ciencia da computação da ufma.http://www.deinf.ufma.br/~lrc/2009.1/LP/
- [K&R] KERNIGHAN, B. e RITCHIE, D. (1990) C, a linguagem de programação: padrão ANSI. Rio de Janeiro: Campus.
- DEITEL, H. M. (1999) Como programar em C. Rio de Janeiro: LTC.
- Módulo Consultoria e Informática (1989) Linguagem C: programação e aplicações. Rio de Janeiro: LTC.
Coloque aqui o seu email