Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Ling ProgC - aula 05 - PONTEIROS, Notas de aula de Engenharia Informática

Linguagem C - Ponteiros

Tipologia: Notas de aula

2011

Compartilhado em 13/03/2011

ademi-venceslau-1
ademi-venceslau-1 🇧🇷

4.5

(2)

16 documentos

1 / 20

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Linguagem de Programação C
Prof. Paulo Caetano
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14

Pré-visualização parcial do texto

Baixe Ling ProgC - aula 05 - PONTEIROS e outras Notas de aula em PDF para Engenharia Informática, somente na Docsity!

Linguagem de Programação C

Prof. Paulo Caetano

PONTEIROS

-^

Como Funcionam os Ponteiros

-^

int

armazena inteiros;

float

armazena números de ponto flutuante.

char

armazena caracteres.

-^

Ponteiros guardam endereços de memória

Quando você anota o endereço de um colega você está criando um ponteiro.

Qual é o sentido disto? Quando você anota o endereço de um colega, depoisvocê vai usar este endereço para achá-lo. Em C funciona desta mesmamaneira, você anota o endereço de algo numa variável ponteiro para depois usar.usar.

Uma agenda, onde são guardados vários endereços , poderia ser vista comosendo uma matriz de ponteiros em C.

-^

Um ponteiro tem tipo.

quando você anota um endereço de um amigo você o trata diferente dequando você anota o endereço de uma firma. Apesar de o endereço dos doislocais ter o mesmo formato (rua, número, bairro, cidade, etc.) eles indicamlocais cujos conteúdos são diferentes. Então os dois endereços são ponteirosde

tipos

diferentes.

Em C quando declaramos ponteiros, informamos ao compilador para que tipode variável vamos apontá-lo. Um ponteiro

int

aponta para um inteiro, isto é,

guarda o endereço de um inteiro.

PONTEIROS

-^

Para atribuir um valor a um ponteiro recém-criado poderíamos igualá-lo aum valor de memória.

Como saber a posição na memória de uma variável do nosso programa? Seriamuito difícil saber o endereço de cada variável que usamos, mesmo porque estesendereços são determinados pelo compilador na hora da compilação erealocados na execução.

O compilador faz este trabalho.

Para saber o endereço de uma variável basta usar o operador &.

int count=10;

int *pt;

pt=&count;

Criamos um inteiro

count

com o valor 10 e um apontador para um inteiro

pt

. A

expressão

&count

nos dá o endereço de

count

, o qual armazenamos em

pt

.

-^

Como foi fornecido um endereço a

pt

, ele está "liberado" para ser usado.

-^

Pode-se, por exemplo, alterar o valor de

count

usando

pt

. Para tanto

vamos usar o operador "inverso" do operador

=> o operador

Como

pt=&count,

a expressão

*pt

é equivalente ao próprio

count

.

Isto significa que para mudar o valor de

count

para 12, basta fazer

*pt=

.

PONTEIROS

#include <stdio.h>int main (){

int num,valor;int *p;num=55;p=#

/* Pega o endereco de num */

valor=*p;

/*

valor

é igualado a

num

de uma maneira indireta */

printf ("\n\n%d\n",valor);printf ("Endereco para onde o ponteiro aponta: %p\n",p);printf ("Valor da variavel apontada: %d\n",*p); return(0); }^

return(0); } #include <stdio.h>int main (){

int num,*p;num=55;p=#

/* Pega o endereco de num */

printf ("\nValor inicial: %d\n",num);p=100; / Muda o valor de num de uma maneira indireta */printf ("\nValor final: %d\n",num);return(0); }

o código

%p

usado na função

printf()

indica à função que

ela deve imprimir um endereço

PONTEIROS

Operações com ponteiros

-^

Soma e subtração de inteiros com ponteiros. Vamos supor que você queiraincrementar um ponteiro de 15:

p=p+15;

ou

p+=15;

•^

Para usar o conteúdo do ponteiro 15 posições adiante;

*(p+15);

•^

Comparação entre dois ponteiros.

-^

Comparação entre dois ponteiros.

Para saber se dois ponteiros são iguais ou diferentes (

e

No caso de operações do tipo

,^
,^

e

estamos comparando qual ponteiro

aponta para uma posição mais alta

na memória

. Então uma comparação entre

ponteiros pode nos dizer qual dos dois está "mais adiante" na memória. Acomparação entre dois ponteiros se escreve como a comparação entre outrasduas variáveis quaisquer:

p1>p

•^

Há entretanto operações que você

não

pode efetuar num ponteiro. Você não pode

dividir ou multiplicar ponteiros, adicionar dois ponteiros, adicionar ou subtrair float

s^

ou

double

s^

de ponteiros.

PONTEIROS

-^

Exercícios a) Explique a diferença entrep++;

(*p)++;

*(p++);

O que quer dizer *(p+10);?

Explique o que você entendeu da comparação entre ponteiros

b) Qual o valor de y no final do programa? Tente primeiro descobrir e depois verifique no

computador o resultado. A seguir, escreva um /* comentário */ em cada comando deatribuição explicando o que ele faz e o valor da variável à esquerda do '=' após sua execução. int

main() int

main() {

int y, p, x;y = 0;p = &y;x = p;x = 4;(p)++;x--;(p) += x;printf ("y = %d\n", y);return(0); }

PONTEIROS

-^

Ponteiros e Vetores

-^

Vetores como ponteiros

-^

Agora podemos entender como é que funciona um vetor!

-^

Fica claro, por exemplo, porque é que, no C, a indexação começa com zero.

É porque, ao

pegarmos o valor do primeiro elemento de um vetor, queremos, de fato, *nome_da_variável

e

então devemos ter um índice igual a zero

. Então sabemos que:

*nome_da_variável

é equivalente a

nome_da_variável[0]

-^

Apesar de, na maioria dos casos, não fazer muito sentido, poderíamos ter

índices negativos

.

Estaríamos pegando posições de memória antes do vetor

.

Estaríamos pegando posições de memória antes do vetor

.

Isto explica também porque C não verifica a validade dos índices. Ele

não

sabe o

tamanho do vetor. Ele apenas aloca a memória, ajusta o ponteiro do nome do vetor parao início do mesmo e, quando você usa os índices, encontra os elementos requisitados.

-^

Vamos ver agora um dos usos mais importantes dos ponteiros: a varredura sequencial deuma matriz. Quando temos que varrer todos os elementos de uma matriz de uma formasequencial, podemos usar um ponteiro, o qual vamos incrementando. Qual a vantagem?Considere o seguinte programa para zerar uma matriz:

10

PONTEIROS

-^

Ponteiros e Vetores

-^

Vetores como ponteiros

-^

Vamos ver agora um dos usos mais importantes dos ponteiros: a

varredura sequencial de uma matriz

. Quando

temos que varrer todos os elementos de uma matriz de uma forma sequencial, podemos usar um ponteiro, oqual vamos incrementando. Qual a vantagem? Considere o seguinte programa para zerar uma matriz: int main (){

float matrx [50][50];int i,j;for (i=0;i<50;i++)

for (j=0;j<50;j++)matrx[i][j]=0.0;

return(0);} Podemos reescrevê

  • lo usando ponteiros:

int main (){

float matrx [50][50];float *p;int count;p=matrx[0];for (count=0;count<2500;count++)

{

*p=0.0;p++;

} return(0);}

-^

No primeiro programa,

cada

vez que se faz

matrx[i][j]

o programa tem que calcular o deslocamento para dar ao

ponteiro. Ou seja, o programa tem que calcular 2500 deslocamentos. No segundo programa o único cálculo quedeve ser feito é o de um incremento de ponteiro. Fazer 2500 incrementos em um ponteiro é muito mais rápidoque calcular 2500 deslocamentos completos.

PONTEIROS

-^

Ponteiros e Vetores

-^

Ponteiros como vetores

-^

Sabemos que o nome de um vetor é um ponteiro constante.

-^

Sabemos que podemos indexar o nome de um vetor.

-^

Como conseqüência podemos indexar um ponteiro qualquer. O programa mostrado a seguirfunciona perfeitamente: #include <stdio.h>int main () {{

int matrx [10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *p;p=matrx;printf ("O terceiro elemento do vetor e: %d",p[2]);return(0); } Podemos ver que

p[2]

equivale a

*(p+2)

.

PONTEIROS

-^

Strings

-^

Seguindo o raciocínio acima, nomes de strings, são do tipo

char*

. Isto nos permite escrever a

nossa função

StrCpy()

, que funcionará de forma semelhante à função

strcpy()

da biblioteca:

#include <stdio.h>void StrCpy (char *destino,char *origem){

while(*origem){ destino=origem;origem++;destino++;^ }

Observe que podemos passar ponteiros comoargumentos de funções

.

Funções como

gets()

e

strcpy()

funcionam assim.

Passando o ponteiro, a função pode

alterar

o

conteúdo das strings. Já estávamos passando os ponteiros. No comando

while (origem)*

, usamos o fato de que

a string termina com '

\0' como critério de parada.

} *destino='\0';

} int main (){

char str1[100],str2[100],str3[100];printf ("Entre com uma string: ");gets (str1);StrCpy (str2,str1);StrCpy (str3,"Voce digitou a string ");printf ("\n\n%s%s",str3,str2);return(0); }^

a string termina com '

\0' como critério de parada.

Quando fazemos

origem++

e

destino++,

poderia ser

argumentado que estamos alterando o valor doponteiro-base da string, contradizendo o que foirecomendado anteriormente. Entretanto, em C, sãopassados para as funções

cópias

dos argumentos (e

que será estudado em detalhe mais adiante). Desta maneira, quando alteramos o ponteiro

origem

na função

StrCpy()

o ponteiro

str

permanece

inalterado na função

main()

.

PONTEIROS

•^

Inicializando Ponteiros

-^

Toda string que o programador insere no programa é colocada num banco destrings que o compilador cria.

-^

No local onde está uma string no programa, o compilador coloca o endereço doinício daquela string (que está no banco de strings).

-^

Por isto que podemos usar

strcpy()

do seguinte modo:

strcpy (string,"String

constante.");

-^

strcpy()

pede dois parâmetros do tipo

char*

•^

Como o compilador substitui a string

"String constante."

pelo seu endereço no

banco de strings, tudo está bem para a função

strcpy()

banco de strings, tudo está bem para a função

strcpy()

•^

O que isto tem a ver com a inicialização de ponteiros? Para uma string que vamosusar várias vezes, podemos fazer:

char *str1="String constante.";

•^

Então poderíamos, em todo lugar que precisarmos da string, usar a variável

str

•^

Deve-se ter cuidado ao usar este ponteiro:

Se o alterarmos vamos perder a string

.

Se o usarmos para alterar a string podemos facilmente corromper o banco de stringsque o compilador criou.

•^

Mais uma vez fica o aviso: ponteiros são poderosos mas, se usados com descuido,podem ser uma ótima fonte de bugs.

16

PONTEIROS

•^

Exercício

-^

Escreva a função

int strend(char *s, char *t)

que retorna 1 (um) se a cadeia de

caracteres

t

ocorrer no final da cadeia

s

, e 0 (zero) caso contrário.

PONTEIROS

•^

Exercicio

-^

Verifique o programa abaixo. Encontre o seu erro e corrija-o para que escreva onumero 10 na tela.#include <stdio.h>int main(){

int x, *p, **q;p = &x; q = &p;q = &p; x = 10;printf("\n%d\n", &q);return(0); }

PONTEIROS

•^

Cuidados a Serem Tomados ao se Usar Ponteiros

-^

Principais cuidados ao se usar um ponteiro:

saiba sempre

para onde

o ponteiro está apontando.

nunca use um ponteiro que não foi inicializado.

•^

Um pequeno programa que demonstra como

não

usar um ponteiro:

int main ()

/ Errado - Nao Execute /

{^

int x,*p;x=13; p=x;p=x; return(0);}

-^

Este programa compilará e rodará. O que acontecerá? Não se sabe.

O ponteiro p pode estar apontando para qualquer lugar.

Você estará gravando o número 13 em um lugar desconhecido.

Com um número apenas, você provavelmente não vai ver nenhum defeito.

Agora, se você começar a gravar números em posições aleatórias no seu computador, não vaidemorar muito para travar o micro (se não acontecer coisa pior).

•^

Exercício:

Escreva um programa que declare uma matriz 100x100 de inteiros. Você

deve inicializar a matriz com zeros usando ponteiros para endereçar seuselementos. Preencha depois a matriz com os números de 1 a 10000, também usando ponteiros.