Você está na página 1de 11

C++ - Ponteiros Um ponteiro um endereo de memria.

. Seu valor indica onde uma varivel est armazenada, no o que est armazenado. Uso : Algumas razes para uso de ponteiros : receber argumentos em funes que necessitem modificar o argumento original; manipular elementos de matrizes; passar strings de uma funo para outra; us-los no lugar de matriz; criar estruturas de dados complexas, como listas encadeadas e rvores binrias, onde um item deve conter referncias a outro; alocar e liberar memria do sistema. Passando argumentos por referncia com ponteiros : H trs maneiras de passar argumentos para uma funo : por valor por referncia por ponteiro Para usar ponteiros como argumentos, seguir dois passos : a funo chamadora passa endereos das variveis onde queremos que a funo coloque novos valores, usando o operador de endereos &; a funo chamada deve criar variveis (ponteiros) para armazenar os endereos enviados pela funo chamadora. Ex.: Por referncia (exemplo visto no captulo de funes) void reajusta20 (float& p, float& r); void main ( ) { float preco, val_reaj; ... reajusta20 ( preco, val_reaj); ...

// chamada

} void reajusta20 (float& p, float& r) { r = p * 0.2; p *= 1.2; } Por ponteiro : void reajusta20 (float *p, float *r); void main ( ) { float preco, val_reaj; ... reajusta20 ( &preco, &val_reaj); ... }

// chamada

void reajusta20 (float *p, float *r) { *r = *p * 0.2; *p *= 1.2; } operador indireto * : resulta o valor da varivel apontada. Na declarao, o smbolo * indica o tipo apontado, enquanto em outras instrues indica a varivel apontada por. C++ permite ponteiros de qualquer tipo e as seguintes sintaxes de declarao: Operador indireto junto ao nome da varivel: int *p; // ponteiro int char *p; // ponteiro char String *p; // ponteiro para um tipo definido pelo usurio Operador indireto junto ao nome do tipo : int* p; // ponteiro int char* p; // ponteiro char String* p; // ponteiro para um tipo definido pelo usurio

Vrios ponteiros numa mesma instruo : int* p, * p1, * p2; int *p, *p1, *p2; Inicializando ponteiros : int i; int *pi = &i; int *pj, *pi = &i, *px; Ponteiros e variveis simples declarados numa nica instruo : int *p, i, j, *q; int *px = &x, i, j = 5; *q; Operaes com ponteiros : Veja o exemplo do que se pode operar . #include <iostream.h> void main ( ) { int x = 5, y = 6; int *px, *py; px = &x; py = &y; // atribuies

if (px < py ) // comparaes entre ponteiros de mesmo tipo cout << \px - py = << (px-py); else cout << \py - px = << (py-px); cout << \npx = << px << , *px = << *px << , &px = << &px; py++; cout << \npy = << py << , *py = << *py << , &py = << &py; px = py + 3; // operador indireto // operador de endereo // incremento

// soma com nmero

cout << \npx = < < px << , *px = << *px << , &px = << &px; cout << \npx - py = << (px - py); ... // diferena entre ponteiros

Observ. : A unidade com ponteiros o nmero de bytes do tipo apontado. Ponteiros no lugar de matriz : Os seguintes programas imprimem os valores dos elementos de uma matriz: usando indexao void main ( ) { int M[5] = { 92, 81, 70, 69, 58}; for (int i = 0; i < 5; i++) cout << \n << M[i]; } usando ponteiro constante void main ( ) { int M[5] = { 92, 81, 70, 69, 58}; } for (int i = 0; i < 5; i++) usando ponteiro varivel void main ( ) { int M[5] = { 92, 81, 70, 69, 58}; int *p = M; } for (int i = 0; i < 5; i++) cout << \n << *(p++); cout << \n << *(M + i);

Observ. :

M+i equivalente a &M[i] *(M + i) equivalente a M[i] O nome de uma matriz um ponteiro constante, logo *(M++) errado.

Passando matrizes como argumento de funes : usando notao de matriz ([]) int media (int lista[ ], int tamanho) // ponteiro constante usando notao ponteiro int media (int *lista, int tamanho) { int m = 0; for (int i=0; i<tamanho; i++) return (m / tamanho); } // ponteiro varivel m += *lista++;

Precedncia : Os ponteiros unrios so resolvidos da direita para esquerda, logo, *lista++ ser interpretado como *(lista++), ou seja o ponteiro, no o contedo, ser incrementado. Ponteiros e Strings : Strings so simplesmente matrizes do tipo char. Desta forma, a notao de ponteiro pode ser aplicada a strings do mesmo modo que aplicada a matrizes. Funes de Biblioteca para manipulao de strings usando ponteiros: strlen ( ) retorna o comprimento da cadeia. int strlen (char *s) { int i=0; while(*s) {i++; s++;} return i; } strcpy( ) copia a cadeia origem na cadeia destino. void strcpy (char *dest, char *orig) { while(*dest++ = *orig++); strcmp( ) compara cadeias. int strcmp (char *s, char *t) {

while(*s==*t && *s && *t) { s++; t++; } return *s - *t; Prtica X Refaa seu trabalho sobre strings, usando ponteiros.

Matrizes de Ponteiros : O uso mais comum na construo de matrizes de ponteiros para strings. Observe o exemplo : (ponteiro constante) usando notao de matriz ([ ]) char diasemana[7][14] = { Domingo, Segunda -feira, Tera -feira, Quarta -feira, Quinta -feira, Sexta -feira, Sbado }; (ponteiro varivel) usando notao ponteiro char *diasemana[7] = { Domingo, Segunda -feira, Tera -feira, Quarta feira, Quinta -feira, Sexta-feira, Sbado }; Na verso matriz, as strings so guardadas na memria em 7 posies de 14 bytes cada uma, ou seja, ocupando 98 bytes de memria. Na verso ponteiro, elas so guardadas de forma a ocupar somente o nmero de bytes necessrios para o seu armazenamento, neste exemplo, 79 bytes, contados os bytes dos \0. Concluso : Inicializar uma matriz de strings usando ponteiros aloca menos memria que a inicializao por meio de matriz. rea de alocao dinmica : HEAP consiste em toda memria disponvel que no foi usada para outro propsito, ou seja, o resto da memria. C++ oferece operadores que permitem a alocao (new) ou a liberao (delete) dinmica de memria de heap. Alocando e desalocando memria : O operador new obtm memria do sistema e retorna um ponteiro para o primeiro byte do novo bloco de memria que foi alocado. Esta memria continua ocupada at que seja liberada explicitamente pelo operador delete. Ex.: Operador new e delete na classe string. class string { private :

char *str; public : string ( ) { str = new char; } *str = \0;

// uso de ponteiro // construtor sem argumento /* alocao de 1 byte de memria, endereo em str */ // inicializa contedo com /0

string (char *s) // construtor com argumento { str = new char[strlen(s) + 1]; /* alocao de memria strcpy (str, s); } ~string( ) { if(str) delete str; } /* se a memria foi alocada, libera */ void print( ) {cout << str;} void operator +=(const char *s) { char *temp; int tamanho = strlen(str) + strlen(s); temp = new char[tamanho+1]; strcpy(temp,str); strcat(temp,s); delete str; str = temp;

};

void main ( ) { string s1(C++ : ), s2; s1 += Linguagem orientada a objetos;

cout << \n; s1.print( ); s2 = s1; cout << \n; s2.print( );

// atribuio entre ponteiros

Observ. : s2.str e s1.str apontaro para a mesma localizao de memria. Logo qualquer modificao em um dos objetos afetar diretamente o outro. Quando o destrutor de um chamado, destruir a memria apontada tambm pelo outro. Soluo : sobrecarregar o operador de atribuio void operator= (const string &s) // verso 1 { int tamanho = strlen(s.str); //calcula tamanho de s delete str; /* libera a memria alocada para objeto atual */ str = new char[tamanho+1]; // aloca nova memria strcpy(str, s.str); /* copia a cadeia de s no objeto atual */ } s1 = s1; Problema : Atribuio de um objeto a si mesmo: Ao alocar nova memria ao ponteiro str, esta contm valores chamados lixo os quais sero copiados nela mesmo, causando resultados absurdos. Soluo : usar o ponteiro this (ponteiro que aponta para o prprio objeto) para testar quando um objeto passado como argumento o mesmo do qual a funo membro. void operator= (const string &s) { if (&s == this) return; int tamanho = strlen(s.str); delete str; str = new char[tamanho+1]; strcpy(str, s.str); // verso 2 /* se for, retorna sem atribuir */

Ainda problema : Instrues mltiplas como :

s3 = s2 = s1;

A funo operator= ( ) do tipo void e toda operao executada por ela no tem valor de retorno. Soluo : Modificar a funo operator= ( ) para que ela retorne o objeto do qual membro, atravs do contedo do elemento apontado pelo ponteiro this, isto , *this. string& operator= (const string &s) { if(&s == this ) return *this; int tamanho = strlen(s.str); delete str; str = new char[tamanho+1]; strcpy(str, s.str); return *this; } void main( ) { string s1="Bom dia ! ", s2, s3; s3=s2=s1; s1.print(); s2.print(); s3.print();

Observ. : this um ponteiro constante; desta forma seu contedo no pode ser alterado para que aponte para outro objeto qualquer. Exerccios (faa com auxlio do computador) 1 Escreva uma instruo que imprima o endereo da varivel x. 2 O que significa o operador asterisco em cada um dos seguintes casos: a) int *p; b) cout << *p; c) *p = x*5; d) cout << *(p+1); 3 Assuma as declaraes abaixo e indique qual o valor das seguintes expresses: int i=3, j=5; int *p = &i; *q = &j; a) p == &q; b) *q-*; c) **&p; d)3*-*p/(*q)+7; 4 Qual a sada deste programa?

#include <iostream.h> void main( ) { int i=5, *p; p = &i; cout << p << \t << (*p+2) << \t << **&p << \t << (3**p) << \t << (**&p+4); } 5 Se i e j so variveis inteiras e p e q ponteiros para int, quais das seguintes expresses de atribuio so incorretas? a) p = &i; b) *q=&j; c) p=&*&i; d) i=(*&)j; e) i=*&*&j; f) q=&p; g) i=(*p)++ + *q; h) if(p==i)i++; 6) Qual a diferena entre: mat[3] e *(mat+3)? 6 O que fazem os seguintes programas: #include <iostream.h> void main( ) { int mat[ ] = {4, 5, 6}; for(int j=0; j<3; j++) cout << \n << *(mat+j); } void main( ) { int mat[ ] = {4, 5, 6}; for(int j=0; j<3; j++) cout << \n << (mat+j); } void main( ) { int mat[ ] = {4, 5, 6}; int *p=mat; for(int j=0; j<3; j++) cout << \n << *p++; } 7 Qual a diferena entre as duas instrues seguintes? Char s[ ] = Brasil; Char *s = Brasil ;

8 Assumindo a declarao: Char *s = Eu no vou sepultar Cesar; O que imprimiro as seguintes instrues: a) cout << s; b) cout << &s[0]; c) cout << (s+11); d) cout << s[0]; 9 Admitindo a declarao : int mat[8]; Por que a instruo mat++; incorreta? Quais das seguintes expresses referenciam o valor do terceiro elemento da matriz? a) *(mat+2); b) *(mat+3); c) mat+2; d) mat+3 10 Qual o erro deste trecho de programa: { ... float x = 333.33; void *p = &x; cout << *p; ...