Anda di halaman 1dari 79

Hernane Borges de Barros Pereira

Criado em fevereiro de 1994

ltima atualizao: 14 de agosto de 2008

Introduo Aritmtica com ponteiros Ponteiros e argumentos de funes Ponteiros e vetores Vetores de ponteiros Equivalncia entre ponteiros e vetores Ponteiros para funes Referncias (alguns comentrios sobre)

Os ponteiros so variveis que guardam endereos de memria char vc=5; Por exemplo: char *p,**pp;
p=&vc; pp=&p;

Variveis Descrio Endereo de memria Contedo Tipo

vc 100 5 Normal

*p 1001 100 Ponteiro

**pp 2500 101 Ponteiro Para Ponteiro

Introduo 01/15

Correspondncia para variveis que contenham endereo na memria onde objetos de um tipo qualquer residam Um ponteiro aponta para algum lugar ou objetos na memria
MEMRIA **pp vc *p 5 100 1001

Loudon (2000) Introduo 02/15

Passagem de parmetros por referncia Passagem de parmetros (vetores e matrizes) Manipulao de matrizes Alocao dinmica Estruturas de dados (e.g. listas encadeadas, rvores binrias,...) Etc.

Introduo 03/15

Recurso importante para:


Trabalho com estrutura de dados dinmicas Manipulao de memria

Situaes inconvenientes:
Problemas imprevisveis E.g. um ponteiro pode apontar para um lugar invlido Ponteiros que oscilam

Introduo 04/15

Ponteiros que oscilam:


Escolha arbitrria de inteiros para ponteiros Deslocamento de ponteiros para alm do limite de um vetor Desalojamento de armazenagem que um ponteiro tem como referncia

H uma dificuldade em visualizar o funcionamento de um ponteiro:


Desenhar diagramas

Redobrar a ateno!
Introduo 05/15

Alocao:
Normalmente ocupam uma palavra de mquina
O tamanho dos registradores (i.e. da palavra) indica a quantidade de dados com a qual o computador pode trabalhar em um momento

Dependncia das verses da Linguagem C (compilao e especificao de tipos permitidos)

No devemos assumir que um ponteiro tem um tamanho definido


Introduo 06/15

Alocao:
Espao somente para o prprio ponteiro nenhum espao alocado para os dados de referncia. O compilador atribui cada varivel a uma nica localizao de memria

Loudon (2000, p. 13) Introduo 07/15

Formas de armazenzamento:
Declarao de uma varivel para o ponteiro Sintaxe:
<tipo> *<nome_da_variavel>;
float *p;

Alocao dinmica
(tipo *) malloc(sizeof(tipo))

Introduo 08/15

Vazamento de memria:
Blocos de armazenagem alocados e no liberados, mesmo eu no estejam mais em uso

Soluo:
Gerenciamento do armazenamento:
Inicializao de estruturas de dados Destruio de estruturas de dados (i.e. liberao de memria)

Estrutura de dados (e.g. listas encadeadas)


Loudon (2000) Introduo 09/15

Declarao:
* (no endereo)
int i, *pi, **ppi;

Obteno de endereo de memria:


& (o endereo de)
pi=&i; ppi=&pi;

Os operadores * e & tm maior precedncia do que todos os operadores aritmticos, exceto o menos unrio
Introduo 10/15

int i, *pi, **ppi; pi=&i; ppi=&pi;

Endereos de memria

i pi ppi
90 9F

90 9F 100

pi ppi

Introduo 11/15

int i, *pi, **ppi; pi=NULL; ppi=&pi;

Endereos de memria

pi ppi

NULL 9F

i pi ppi

90 9F 100

E quando um ponteiro no aponta para nenhum endereo de memria?


Introduo 12/15

int i, *pi, **ppi; pi=&i; ppi=NULL;

Endereos de memria

i pi ppi
E neste caso?
90 NULL

90 9F 100

pi ppi

Introduo 13/15

Este trecho de cdigo equivale a qu?


int i=5,j=0; int *p; p=&i; j=*p; *p=2;

j=i; i=2;

Introduo 14/15

#include<Stdio.h> das variveis declaradas? main() { int i=5,j=0; int x, *px, **ppx; int *p; char*p; int a; float vetor[10]; px=&x; ppx=&px; p=&i; j=*p; *p=2; printf(Tam. Vetor: %d\t Tam. Ponteiro p: %d\t Tam. a: %d, sizeof(vetor), sizeof(*p), sizeof(a) ); }

Quais os contedos e endereos

Introduo 15/15

Dados agregados:
Dados compostos de elementos mltiplos agrupado
Estruturas Tipo registro Vetores/Matizes

Aritmtica com ponteiros 01/05

Aritmtica:
Associao de cada ponteiro com um tipo base determinado feita atravs do tipo base do ponteiro Operaes:
Adio Subtrao

Aritmtica com ponteiros 02/05

Considere:
pf = ponteiro de float vet = vetor de float
#include <Stdio.h> main() { float *pf; float vet[20]; pf = vet; pf++; pf = pf + 2; pf--; vet++; }

O que acontecer?

Aritmtica com ponteiros 03/05

Cada vez que um ponteiro incrementado, ele passa a apontar para a posio de memria do *pi; prximo elemento do seu tipo base. int pi++; Cada vez que decrementado, ele aponta para a pi--; posio do elemento anterior. Observao:
Ponteiros para variveis do tipo caractere segue as regras supracitadas

Schildt (1997, p. 117) Aritmtica com ponteiros 04/05

No possvel multiplicar ou dividir ponteiros No possvel usar os operadores de deslocamento e de mascaramento bit a bit com ponteiros No possvel adicionar ou subtrair o tipo float ou double a ponteiros

Schildt (1997) Aritmtica com ponteiros 05/05

...

Modularizao:
Por valor Por referncia
Programa principal Sequncia de cdigo repetido
...

// Prottipo das funes int funcao1([parmetros]); // Programa principal main() { ... funcao1([parmetros]); ... }
Reestruturao

Uso

Mdulo <Nome>([Parmetros]) { Comando 1; Comando 2; ... retorno [<valores>]; }

Programa principal
<Nome>(Parmetros);

// Corpo da funo declarada anteriormente int funcao1([parmetros]) { ... // Corpo (i.e. bloco de instrues) ... return [valor(es)]; }

...

...

...

<Nome>(Parmetros);

<Nome>(Parmetros);

<Nome>(Parmetros);

...

...

...

...

Chamada ao mdulo Retorno ao programa principal

Ponteiros e argumentos de funes 01/20

Mdulos (i.e. procedimentos e funes) podem ou no receber dados de quem (i.e. funo cliente) os invoca Conceito:
So dados recebidos pelo mdulo que foram passados no ato de sua chamada

Requisitos:
Devem possuir o mesmo tipo dos parmetros enviados pela parte do cdigo que chamou o mdulo
Ponteiros e argumentos de funes 02/20

Procedimentos:
PROC <Nome>([Parmetros]) { Bloco de instrues Retorne; }

Funes:
Tipo FUNC <Nome>([Parmetros]) { Bloco de instrues Retorno <valor>; }

Parmetros: ...<Nome> (tipo <nome da varivel>, tipo <nome da varivel>, ...) { ... }

Ponteiros e argumentos de funes 03/20

Tipos de manipulao:
Por valor:
Cpia do contedo

Por referncia:
Endereo da varivel Operadores: &, *

Ponteiros e argumentos de funes 04/20

Por valor:
Cpia do contedo
Funo Cliente() { ... p = 5; Mdulo(p); ... } Mdulo(p) { ... retorno [<valores>]; }

p 5 p 5
Ponteiros e argumentos de funes 05/20

Por valor:
Cpia do contedo
Funo Cliente() { ... p = 5; Mdulo(p); ... }

O que acontecer?
Mdulo(p) Ponteiro de { fluxo de ... execuo p = 7; retorno [<valores>]; }

p 5 p 5
Ponteiros e argumentos de funes 06/20

Por valor:
Cpia do contedo
Funo Cliente() { ... p = 5; Mdulo(p); ... } Mdulo(p) { ... p = 7; retorno [<valores>]; }

p 5 p 7
Ponteiros e argumentos de funes 07/20

Por referncia:
Endereo da varivel
Funo Cliente() { ... Endereo de p p = 5; Mdulo(&p); ... } Mdulo(*p) { ... retorno [<valores>]; }

Operadores: & (endereo) * (ponteiro)

Endereo de p (&p)

5 *p

Ponteiros e argumentos de funes 08/20

Por referncia:
Endereo da varivel
Funo Cliente() { ... Endereo de p p = 5; Mdulo(&p); ... }

O que acontecer?
Mdulo(*p) Ponteiro de { fluxo de ... execuo p = 7; retorno [<valores>]; }

Operadores: & (endereo) * (ponteiro)

Endereo de p (&p)

5 *p

Ponteiros e argumentos de funes 09/20

Por referncia:
Endereo da varivel
Funo Cliente() { ... Endereo de p p = 5; Mdulo(&p); ... } Mdulo(*p) { ... p = 7; retorno [<valores>]; }

Operadores: & (endereo) * (ponteiro)

Endereo de p (&p)

7 *p

Ponteiros e argumentos de funes 10/20

Em Linguagem C:
// Passagem de Parametro #include "stdio.h" #include "stdlib.h" void trocanao(float, float); void trocasim(float *, float *); void trocatalvez(float &, float &); int main(int argc, char* argv[]) { float x=7.0, y=13.0; printf("x= %f\ty= %f\n", x, y); trocanao(x, y); printf("x= %f\ty= %f\n", x, y); trocasim(&x, &y); printf("x= %f\ty= %f\n", x, y); trocatalvez(x, y); printf("x= %f\ty= %f\n", x, y); system("pause"); return 0; }

void trocanao(float copia_1_de_x, float copia_1_de_y) { float auxiliar; auxiliar = copia_1_de_x; copia_1_de_x = copia_1_de_y; copia_1_de_y = auxiliar; printf("Funcao trocanao x= %f\ty= %f\n",copia_1_de_x , copia_1_de_y); return; } void trocasim(float *copia_2_de_x, float *copia_2_de_y) { float auxiliar; auxiliar = *copia_2_de_x; *copia_2_de_x = *copia_2_de_y; *copia_2_de_y = auxiliar; printf("Funcao trocasim x= %f\ty= %f\n",*copia_2_de_x , *copia_2_de_y); return; } void trocatalvez(float &a, float &b) { float auxiliar; auxiliar = a; a = b; b = auxiliar; printf("Funcao trocatalvez x= %f\ty= %f\n", a, b); return; }

Ponteiros e argumentos de funes 11/20

#include "stdio.h" #include "stdlib.h" Lista* funcao01(Lista *, int); void funcao02(Lista **, int); main() { Lista *pLista; pLista = NULL; pLista = funcao01(pLista, 7); funcao02(&pLista, 13); system("pause"); return 0; }

Lista* funcao01(Lista *p, int info) { Lista *pAux; pAux = p; return pAux; }

void funcao02(Lista **pp, int info) { Lista *pAux; // Realizam-se as operaes em pAux *pp = pAux; return; }

Ponteiros e argumentos de funes 12/20

Por referncia:
Vantagens:
Temos o controle total sobre a passagem de parmetros

Desvantagens:
Lentido do controle devido ao cancelamento da referncia dos parmetros todas as vezes quantas forem necessrias em uma funo

Ponteiros e argumentos de funes 13/20

Por referncia:
Passagem de vetores para funes (ponteiros no modificveis)
int funcao01(int vet[10]) { vet[0] = 7; return 0; } int funcao02(int *vet) { *vet = 7; return 0; }

So equivalentes?

Informaes sobre o limite so omitidas (no so necessrias para o compilador)

Ponteiros e argumentos de funes 14/20

Por referncia:
Informaes sobre limites so importantes quando tratamos com vetores multidimensionais ou matrizes
int funcao03(int vet[][3]) { vet[3][1] = 13; return 0; }

Todas as dimenses devem ser especificadas, exceto a primeira Possibilita a aritmtica com ponteiros

Ponteiros e argumentos de funes 15/20

Funo de mapeamento:
Matriz bi-dimensional Por linhas: caso particular de ordem lexicogrfica mais comum
Endereco ( y [i, j ]) = E0 + ( ( i 1) n + j 1) tamanho (TipoDado )

Por colunas caso particular (e.g. Linguagem FORTRAN)


Endereco ( y [i, j ]) = E0 + ( ( j 1) m + i 1) tamanho (TipoDado )
Ponteiros e argumentos de funes 16/20

Funo de mapeamento:
Matriz n-dimensional
Endereco ( z [in , in 1 ,..., i2 , i1 ]) = E0 + + ( ih 1) d m tamanho (TipoDado )
h =1 m =1 n h 1

onde

d
m =1

h 1

= d1 d 2 ... d h 1 ;

d
m =1

=1

Ponteiros e argumentos de funes 17/20

int funcao03(int vet[][3]) { vet[3][1] = 13; return 0; }

Representao grfica
0 0 1 2

2 bytes

1 2 3

13

13
[0][0] [0][1] [0][2] [1][0] [1][1] [1][2] [2][0] [2][1] [2][2] [3][0] [3][1] [3][2]

Ponteiros e argumentos de funes 18/20

Argumentos da linha de comando


C:\>_

Para um programa no incio de sua execuo Funo main():


int main(int qtarg, char *arg[])

A quantidade de argumentos (primeiro argumento)

Um ponteiro para um vetor do tipo char (segundo argumento). cada elemento do vetor uma cadeia de caracteres

Ponteiros e argumentos de funes 19/20

#include <stdio.h> #include <stdlib.h> int main(int qtarg, char *arg[]) { int i; for(i=0; i<qtarg; i++) printf(%s\n,arg[i]); system(pause); return; }

De que local executamos o programa? Qual o primeiro elemento de vetor de ponteiros? E os demais?

E se utilizssemos ponteiro para ponteiro, como ficaria o programa?

Ponteiros e argumentos de funes 20/20

Forte relao Seqncia contguo de elementos homogneos Linguagem C converte o vetor em um ponteiro no modificvel que aponta para o primeiro elemento do vetor
int i[10], *pi; pi = i; pi[0] = 7; int i[10], *pi; pi = i; *pi = 7;

So equivalentes?
Loudon (2000) Ponteiros e vetores 01/07

Vetores:
char cadeia[30], *pc; pc = cadeia; pc = &cadeia[0];

cadeia[13]

*(cadeia+13)

*(pc+13)

Vetores multidemensionais ou Matrizes:


int vet[2][3], *pi; pi = vet;

So equivalentes?
*(*(vet+i)+j)

vet[i][j]

Ponteiros e vetores 02/07

Aritmtica com ponteiro vs. Indexao de matrizes:


void puts(char *s) { register int t; for(t=0; s[t]; ++t) putchar(s[t]); return; } void putstr(char *s) { while(*s) putchar(*s++); return; }

As funes em Linguagem C so normalmente escritas com ponteiros Schildt (1997) Ponteiros e vetores 03/07

#include <stdio.h> #include <stdlib.h> main() { static char vetor[]=Eu adoro o C\0; char *pc; pc=&vetor[0]; while(*pc) printf(%c,*pc++); system(pause); return; }

O que acontecer se substituirmos *pc++ por ++*pc?

Escreva a verso deste cdigo para vetor.


Ponteiros e vetores 04/07

vetor[]=Eu adoro o C\0;

u ...

d
*pc++

\0

pc=&vetor[0];

Ponteiros e vetores 05/07

#include <stdio.h> #include <stdlib.h>

O que ser impresso?

main() { int *pi, x=3, y; pi = &x; printf(Ponteiro:%d Pos.Mem.:%x\n, *pi, pi); y = *pi+1; pi = &y; printf(Ponteiro:%d Pos.Mem.:%x\n, *pi, pi); *pi++; printf(Ponteiro:%d Pos.Mem.:%x\n, *pi, pi); system(pause); return; }

Ponteiros e vetores 06/07

x=3 pi=&x;

y=*pi+1;

1000

1001

1002

1003

3 ...

pi=&y;

O que acontecer em *pi++?

Ponteiros e vetores 07/07

Contedo do vetor:
Ponteiros de memria

Vetores de ponteiros vs. Vetores n-dimensionais:


Vantagem Velocidade Desvantagem Gesto mais complexa

Considere:
char *tab[5];

Isso quer dizer que o vetor *tab[5] pode guardar 5 ponteiros de memria

Vetores de ponteiros 01/03

#include <stdio.h> #include <stdlib.h>

O que ser impresso?

main() { static char *tab[]={Eu,Tu,Ele,Ns,Vs,\0}; int i; for(i=0; i<5; i++) printf(Nome: %s\n, tab[i]); system(pause); return; }

Vetores de ponteiros 02/03

Problema:
Fazer um algoritmo que, baseado no programa anterior, ordene os dados do vetor.
Dica: Utilizar as funes da biblioteca string.h: strcmp() e strcpy().

Vetores de ponteiros 03/03

Seja a um vetor e p um ponteiro:


Ponteiros:
p=a; p=a+i; p=&a[i];

Elemento ou objeto apontado (contedo):


a[i]=*p; *(a+i)

Equivalncia entre ponteiros e vetores 01/02

Vetor unidimensional:
d[i]*(d+i) int i,*p,*q,z[10]; p=z+0; q=z+9; q=p+4; i=q-p; /* /* /* /* /* declaraes */ p aponta p/ z[0] */ q aponta p/ z[9] */ q aponta p/ z[4] */ i a diferena=4 */

Vetor n-dimensional:
z[i][j] *(z[i]+j) *(*(z+i)+j) float apf[4]; // ou *(apf[4]) int (*pai)[4] Ponteiro para um vetor de 4 int

Equivalncia entre ponteiros e vetores 02/02

Ponteiros no s apontam para variveis? A memria RAM compartilhada pelos dois:


Variveis Funes

Uma funo no uma varivel

O cdigo da funo possui um endereo de memria (i.e. posio fsica na memria):


Podemos criar ponteiros que apontem para funes e execut-las indiretamente Ponto de entrada da funo
Schildt (1997) Ponteiros para funes 01/08

Quando uma funo compilada:


Cdigo fonte Cdigo-objeto
Ponto de entrada da funo estabelecido

A chamada funo realizada em linguagem de mquina Se existe um ponteiro que aponta para esse ponto de entrada da funo, ele pode ser usado para chamar essa funo
Schildt (1997) Ponteiros para funes 02/08

Sua obteno realizada atravs do nome da funo sem os parnteses e/ou parmetros
#include <stdio.h> #include <stdlib.h> main() { int(*funo)(); funo=printf; (*funo)(Ahrrr! Testando!\n); system(pause); return; }

Assemelha-se maneira como o endereo de um vetor obtido.

char cadeia[30], *pc; pc = cadeia;

Ponteiros para funes 03/08

#include <stdio.h> #include <string.h>

Analisem este cdigo.

void check(char *a, char *b, int (*cmp)(const char *, const char *)); void main(void) { char s1[80], s2[80]; int (*p)(); p = strcmp; gets(s1); gets(s2); check(s1, s2, p); } void check(char *a, char *b, int (*cmp)(const char *, const char *)) { printf("testando igualdade\n"); if(!(*cmp)(a, b)) printf("igual"); else printf("diferente"); }

Schildt (1997, p. 126-127) Ponteiros para funes 04/08

int (*p)(); p = strcmp;

Parnteses ao redor do *p ou do *cmp so necessrios para que o compilador interprete o comando corretamente

Obteno do endereo de memria da funo

(*cmp)(a, b)

check(s1, s2, p);

void check(char *a, char *b, int (*cmp)(const char *, const char *))

Ponteiro para a funo


Ponteiros para funes 05/08

Pode trazer confuso Vantagens em passar funes arbitrrias a mdulos ou em manter uma vetor de funes, e.g.:
switch vs. ponteiros para funes

Ponteiros para funes 06/08

obrigatria a igualdade dos tipos (i.e. do ponteiro e do retorno da funo) Para obter o endereo de uma funo, basta digitar o seu nome sem os parnteses e/ou parmetros usar uma forma semelhante para declarar outros ponteiros para funes, embora o tipo de retorno possa ser diferente.
Schildt (1997, p. 127) Ponteiros para funes 07/08

#include <stdio.h> #include <string.h> void funcao_1(void); void funcao_2(void); void funcao_3(void); void funcao_4(void); void main() { void (*vetor_fun[4])(); int opcao; vetor_fun[0] = funcao_1; vetor_fun[1] = funcao_2; vetor_fun[2] = funcao_3; vetor_fun[3] = funcao_4; printf("\033[2J"); // Limpa a tela printf("Escolha opcao [0,1,2,3]: "); scanf("%d", &opcao); (*vetor_fun[opcao])(); system(pause); return; }

Analisem este cdigo.


void funcao_1() { printf("Estou return; } void funcao_2() { printf("Estou return; } void funcao_3() { printf("Estou return; } void funcao_4() { printf("Estou return; } na funcao_1\n");

na funcao_2\n");

na funcao_3\n");

na funcao_4\n");

Ponteiros para funes 08/08

ASCENCIO, A. F. G. & CAMPOS, E. A. V. Fundamentos da programao de computadores Algoritmos, Pascal, C/C++. Pearson Prentice-Hall, 2005 FERRER, H. et al. Algoritmos Estruturados. 3 edio, Rio de Janeiro: LTC, 1999 SHILDT, H. C Completo e Total. So Paulo: Editora Makron Books, 1997 STALLINGS, W. Arquitetura e Organizao de Computadores. 5 edio, Prentice-Hall, 2005 TANENBAUM, A. Organizao Estruturada de Computadores. Rio de Janeiro: LTC, 2001
Referncias 01/05

AHO, Alfred V.; HOPCROFT, John E. & ULLMAN, Jeffrey D. Data structure and algorithms. Delaware: Addison-Wesley, 1983 CELES, W.; CERQUEIRA; R. F. G. & NETTO, J. L. M. R. Introduo a Estruturas de Dados - com tcnicas de programao em C. Rio de Janeiro: Campus, 2004 CAPPER, D. M. Introducing C++ for scientists, engineers and mathematicians. London: SpringerVerlag, 1994
Referncias 02/05

CORMEN, T. H.; LEISERSON, C. E.; RIVEST, R. L. & STEIN, C. Introduction to Algorithms. 2. Ed. Cidade: The MIT Press and McGraw-Hill, 2001 KERNIGHAN, B. W. C. & RITCHIE, D. M. The C Programming Language - ANSI C. Prentice Hall, 1988 KNUTH, D. E. Art of Computer Programming, Vol.1, Fundamental Algorithms (3rd Ed.), AddisonWesley, 1997 LOUDON, K. Dominando algoritmos cm C. Rio de Janeiro: Ed. Cincia Moderna, 2000.
Referncias 03/05

KORFHAGE, Robert R. Lgica y Algoritmos: Con aplicaciones a las ciencias de la computacin e informacin. Mxico D.F.: Editorial Limusa-Wiley, 1970 SABESTA, Robert. Conceitos de linguagem de programao. Editora Bookman, 2003 SEDGEWICK, R. Algorithms in C++, (3rd Ed.) Boston: Addison-Wesley Publishing Company, 1998 SZWARCFITER, J. L. & MARKENZON, L. Estruturas de Dados e seus Algoritmos. 2nd ed. Rio de Janeiro: LTC, 1994
Referncias 04/05

TENENBAUM, A. M.; LANGSAM, Y. & AUGENSTEIN, M. J. Estruturas de Dados Usando C. So Paulo: Makron Books do Brasil, 1995 TREMBLAY, J. P. & SORENSON, P.G. An introduction to data structures with applications. 2. Ed. Auckland: McGraw-Hill, 1984 WIRTH, N. Algoritmos e Estruturas de Dados, Rio de Janeiro: Prentice-Hall do Brasil, 1989

Referncias 05/05

Digresso 01/03

Digresso 02/03

// Diretivas de pr-processamento #include <stdio.h> // Prottipo das funes - Padro: (tipo) Funo (parmetros); int funcao1([parmetros]); // Definio das variveis Globais e Externas ... // Programa principal main() { // Definio das variveis locais ... // Corpo (i.e. bloco de instrues) ... // Retorno da funo (opcional em alguns casos) return [valor(es)]; } // Corpo da funo declarada anteriormente int funcao1([parmetros]) { // Definio das variveis locais ... // Corpo (i.e. bloco de instrues) ... // Retorno da funo (opcional em alguns casos) return [valor(es)]; }

Definies prvias

Corpo do programa principal

Corpo das funes criadas pelo usurio

Digresso 03/03