Sei sulla pagina 1di 8

Sumário

Introdução à Ciência
 Introdução
da Computação  Definição de Ponteiros
 Declaração de Ponteiros em C
Manipulação de Ponteiros em C
Ponteiros 

 Operações
em C  Ponteiros e Arranjos
Prof. Ricardo J. G. B. Campello  Passagem de Parâmetros por Referência

Introdução Definição

 Por quê ponteiros são importantes?  Um ponteiro (ou apontador) é uma variável
que armazena um endereço de memória
 Permitem passagem de parâmetros para
 Normalmente, esse endereço é a posição de outra
funções por referência variável na memória
 Permitem alocar e liberar memória  Dizemos portanto que um ponteiro “aponta” para
dinamicamente (em tempo de execução) uma variável

 Possibilitam a implementação eficiente de  O tipo do ponteiro é normalmente associado ao tipo


da variável apontada
certas estruturas de dados
3 4
Definição Declaração em C
 tipo *var1, *var2, ...;

...
Exemplo:
1002  O símbolo * indica que as variáveis var1, var2, etc.
1003 conteúdo de A A são ponteiros para variáveis do tipo tipo
1004
1005 1003 P (ponteiro)  Alternativamente pode-se declarar como:
1006
 tipo* var1, var2, ...;

 Exemplos:
...

 float *a, *t23, *lista;


 int* b, s2;
5 6

Manipulação em C Manipulação em C
 Operadores:  Atribuição (P1 e P2 ponteiros – A, B e C variáveis):

 Endereço de Variável para Ponteiro


 Operador de endereço: &
 Exemplos: P1 = &A; P2 = &B;
 Ponteiros só podem receber endereços de memória
 Conteúdo de Endereço Apontado para Variável
 Para isso, pode-se utilizar o operador &
 Exemplo: C = *P2;
 Operador de conteúdo: *
 Ponteiro para Ponteiro (ou para nulo)
 Recupera o conteúdo da variável apontada por um ponteiro
 Exemplos: P1 = P2; P2 = NULL;
 Ponteiro nulo: NULL
 Conteúdo para Endereço Apontado
 Um ponteiro que recebe o valor NULL aponta para nada
 Exemplos: *P1 = A; *P1 = 34;
7 8
Manipulação em C Manipulação em C
#include <stdio.h>
void main(void){
Exemplo: float A, B, *P1, *P2;  Comparação:
A = 3.123;
printf("%f\n", A);  Como para qualquer variável
P1 = &A;
3.123 printf("%f\n",*P1);
 Exemplos:
3.123 *P1 = 2.456;
printf("%f\n",A);
2.456 P2 = P1;
 if (P1 == P2) /* Verifica se P1 e P2 apontam para o mesmo endereço */
2.456 B = *P2;
 if (P1 == NULL) /* Verifica se P1 aponta para NULL */
1.789 printf("%f\n",B);
2.456 B = 1.789;
P2 = &B;
2.456 printf("%f\n%f\n%f\n%f",B, A, *P1, *P2);
1.789 } 9 10

Ponteiros para Estruturas Ponteiros para Estruturas


 Podemos declarar ponteiros para estruturas  No exemplo anterior, poderíamos definir o tipo:
typedef struct {
 Por exemplo:
float campo1;
struct estrutura {
char campo2; } minha_estrutura;
float campo1;
minha_estrutura est, *pt;
char campo2; }
struct estrutura est, *pt;  Em qualquer caso, o acesso aos campos de
uma estrutura através de um ponteiro
 Na verdade, é possível declarar ponteiros
demanda o operador seta ( −> )
para tipos definidos pelo usuário em geral
11 12
Ponteiros para Estruturas Ponteiros e Arranjos
 No exemplo anterior, poderíamos utilizar o operador  Há uma relação estreita entre ponteiros e arranjos
seta para acessar os campos da var. composta est (vetores e matrizes) em linguagem C
através de um ponteiro pt
 Por exemplo, considere as seguintes declarações:
pt = &est;
 char str[10], *p1;
printf("O valor do campo1 é %f", pt->campo1);
 vetor de 10 chars (string) e ponteiro para chars
printf("O valor do campo2 é %c", pt->campo2);
 As seguintes atribuições são equivalentes:
 Notas:
 p1 = str ou p1 = &str[0]
 Operador -> acessa conteúdo, não endereço !
 o nome do vetor referencia o endereço do seu 1º elemento
 pt->campo1 é equivalente a est.campo1  o mesmo vale para matrizes, armazenadas linearmente em memória
 como se fosse um vetor, linha por linha
14

Ponteiros e Arranjos Ponteiros e Arranjos


 Há uma relação estreita entre ponteiros e arranjos  Nota 1: embora o nome do arranjo referencie seu 1º
(vetores e matrizes) em linguagem C elemento, não podemos atribuir ou modificar o valor deste
 Por exemplo, considere as seguintes declarações: como se fosse um ponteiro qualquer
 char str[] = {'b', 'l', 'a', 'b', 'l', 'a', 'b', 'l', 'a', '\0'}, *p1;  ou perderíamos a referência para o início do arranjo...

 vetor de 10 chars (string) e ponteiro para chars  Por exemplo, o seguinte trecho de código não compila:
 As seguintes expressões são equivalentes: char str[]={'b', 'l', 'a', 'b', 'l', 'a', 'b', 'l', 'a', '\0'};

 str[5] ou *(str + 5) while (*str != '\0'){ printf("%c", *str); str++; }

 ambas representam o conteúdo do sexto elemento da string (“a”)  Para corrigir:


 lembrando que arranjos em C são indexados a partir de zero char* p1 = str;
while (*p1 != '\0'){ printf("%c", *p1); p1++; }
15 16
Ponteiros e Arranjos Relembrando Funções...

 Nota 2: a relação entre arranjos e ponteiros é tão  Escopo:


próxima que um ponteiro para um arranjo pode ser  As variáveis declaradas dentro de uma função possuem escopo
indexado como se o próprio arranjo fosse (sem *) local, ou seja, provisório e interno à função
 Variáveis globais são declaradas no início de qualquer módulo
 Por ex., o código anterior poderia ser rescrito como: (arquivo) de programa, fora de qualquer função (incluindo main)
char str[10] = "blablabla", *p1;
 Passagem de Parâmetros:
int i;
 Em geral, por valor (uma cópia do parâmetro é feita)
p1 = str;  Em C ANSI, isso inclui structs
for (i=0; i<9; i++) printf("%c", p1[i]);  Para forçar passagem por referência, é preciso utilizar ponteiros
 É o que ocorre necessariamente com arranjos (vetores/matrizes)
17 18

Funções e Ponteiros Por que Passagem por Referência?


 Em muitas situações em programação, a passagem de
 Passagem por Referência parâmetros por valor não é apropriada
 Alterações feitas nos parâmetros recebidos  Por exemplo, a função abaixo é inócua:
são refletidas nos valores passados como void troca(int x, int y){
argumentos int temp;
temp = x;
 O endereço do argumento é passado no x = y;
momento da chamada da função y = temp; }

 endereço do argumento = ponteiro pois não altera as variáveis passadas como parâmetros,
altera apenas as cópias dos seus valores feitas em x e y
 tais cópias desaparecem ao final da execução da função 20
Passagem de Ponteiros Passagem de Ponteiros
 Para forçar uma passagem por referência, é preciso utilizar ponteiros  Veja como fica uma chamada à função anterior:
void main(void){
 Nesse caso, a função do exemplo anterior fica:
int temp, a = 10, b = 20;
void troca(int *x, int *y){
printf("%d %d\n", a, b);
int temp;
troca(&a, &b);
temp = *x;
printf("%d %d", a, b);
*x = *y;
}
*y = temp;
}  Isso explica a sintaxe de scanf (ou seja, por que devemos incluir o
operador & antecedendo as variáveis a receberem valores) ???
e troca os valores contidos nos endereços passados como parâmetro
 também explica por que isso não se faz necessário no caso de strings...?

21 22

Passagem de Ponteiros Passagem de Ponteiros


 A passagem de arranjos para funções é uma exceção  Exemplo:
à convenção de passagem por valor da linguagem C void imprime_string(char *st) {

 Quando uma função possui um arranjo (vetor/matriz) como while (*st != '\0'){ printf("%c", *st); st++; }
parâmetro, apenas uma cópia do endereço do arranjo é
passada na chamada, não uma cópia do arranjo todo  Formas alternativas equivalentes:
 void imprime_string(char* st) { ... }
 Como já sabemos, o endereço do arranjo é um ponteiro para
o seu 1º elemento e é referenciado pelo seu próprio nome  void imprime_string(char st[]) { ... }

 Exemplos de chamada:
 Exemplo:
 imprime_string("alo!");
 Função para imprimir string sem usar fprintf("%s", var)
 imprime_string(var); /* var = vetor de chars (string) */

23 24
Passagem de Ponteiros Outros Tópicos sobre Ponteiros

 Exemplo:  Ponteiros para Alocação Dinâmica de Memória


#include <stdio.h>  Funções que Retornam Ponteiros
void imprime_vetor(int *v, int tamanho);  Matrizes de Ponteiros
void main(void){  Ponteiros para Ponteiros
int vet[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
imprime_vetor(vet, 10);
 Ponteiros para Funções
}
 ...
void imprime_vetor(int *v, int tamanho) {  Para saber mais ...
int cont;
for (cont=0; cont<tamanho; cont++) printf("%d\n", v[cont]);  (Schildt, 1997)
}
 (Damas, 2007)
26

Exercícios Exercícios
 Explique o que #include <stdio.h>  Definir um tipo de registro (struct) com três campos: um
void main(void){
será apresentado campo numérico real, um campo caractere e um campo
int A=1, B=2, C=3, *P1, *P2, *P3;
como resultado do P1 = &B;
dado por um vetor de inteiros
seguinte código P2 = P1;
 Declarar um registro do tipo acima
P3 = &C;
em C:
*P2 = 5;
C = *P1;  Declarar um ponteiro para esse tipo de estrutura e
P1 = &A; apontá-lo para o registro declarado no item anterior
*P1 = *P3;
printf("%d\n%d\n%d",A, B, C);  Atribuir valores aos campos do registro utilizando o
} ponteiro (ou seja, o operador seta, ao invés do
operador ponto)
27 28
Exercícios Exercícios
 Faça uma função que recebe como parâmetros três  Faça uma função que recebe como parâmetro uma
ponteiros para vetores de inteiros, todos do mesmo string (vetor de caracteres) e o respectivo número
tamanho, tamanho este que também é passado de caracteres válidos (tamanho da string, sem
como parâmetro para a função. Essa função deve contar o \0) como parâmetros. Essa função deve
fazer com que cada célula do terceiro vetor se “inverter” a string, ou seja, fazer com que ela
torne igual à soma das células correspondentes apareça de trás para frente caso seja escrita.
dos outros dois

29 30

Bibliografia
 Schildt, H. "C Completo e Total", 3a. Edição,
Pearson, 1997.
 Damas, L. “Linguagem C”, 10a. Edição, LTC, 2007

31

Potrebbero piacerti anche