Buscar

Funções e Ponteiros em C

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 3, do total de 55 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 6, do total de 55 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você viu 9, do total de 55 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Prévia do material em texto

Bruno Jurkovski
Fábio da Fontoura Beltrão
Felipe Augusto Chies
Kauê Soares da Silveira
Lucas Fialho Zawacki
Marcos Vinicius Cavinato
Revisão da Aula 3
� Na última aula aprendemos o que são 
funções. Estas são uma característica 
muito importante da linguagem C.
� Lembrando que funções recebem 
parâmetros, e que estes podem ser 
passados de duas maneiras:
Revisão da Aula 3
� Por valor:
/* Função que retorna o resultado em float
da divisao de a por b */
float divide (float a, float b)
{
return a / (float) b;
}
int main()
{
float x = 2, y = 3;
printf( “%f” , divide (x , y) );
}
Revisão da Aula 3
� Por referência:
/* Função que atribui à variavel resultado
o valor da divisão de a por b */
void divide_ref (float a, float b, float *resultado)
{
*resultado = a / (float) b;
}
int main()
{
float x = 2, y = 3, res;
divide_ref (x , y, &res); // passamos o endereço de res
printf( “%f” , resultado);
}
Revisão da Aula 3
� Outro aspecto importante sobre funções é
que elas possuem o seu próprio escopo.
void perde_tempo ()
{
int n = 0; //n só existe nesse escopo
while (n < 100000)
n++;
}
int main()
{
int n; // não é o mesmo n que declaramos acima
perde_tempo();
}
Ponteiros
Na aula de hoje vamos entender os 
ponteiros. Inicialmente, podem causar 
dúvidas quanto a sua real importância, 
mas com exemplos, ficará fácil de 
compreender seu funcionamento e 
utilidade.
� Toda programação com uma 
linguagem imperativa como o C 
envolve o manuseio de dados 
através de variáveis
� Uma variável, na verdade, é uma 
região de memória específica 
para guardar um determinado 
dado
Introdução
... ...
501
502
503
504
505
506
507
... ...
#include <stdio.h>
int a;
int b[5];
main(){
a = 6;
b[0] = 10;
b[4] = 25;
... 
� Toda programação com uma 
linguagem imperativa como o C 
envolve o manuseio de dados 
através de variáveis
� Uma variável, na verdade, é uma 
região de memória específica 
para guardar um determinado 
dado
Introdução
... ...
501
502
503
504
505
506
507
... ...
#include <stdio.h>
int a;
int b[5];
main(){
a = 6;
b[0] = 10;
b[4] = 25;
... 
� Toda programação com uma 
linguagem imperativa como o C 
envolve o manuseio de dados 
através de variáveis
� Uma variável, na verdade, é uma 
região de memória específica 
para guardar um determinado 
dado
Introdução
#include <stdio.h>
int a;
int b[5];
main(){
a = 6;
b[0] = 10;
b[4] = 25;
... 
... ...
501 6
502
503
504
505
506
507
... ...
� Toda programação com uma 
linguagem imperativa como o C 
envolve o manuseio de dados 
através de variáveis
� Uma variável, na verdade, é uma 
região de memória específica 
para guardar um determinado 
dado
Introdução
#include <stdio.h>
int a;
int b[5];
main(){
a = 6;
b[0] = 10;
b[4] = 25;
... 
... ...
501 6
502 10
503
504
505
506
507
... ...
� Toda programação com uma 
linguagem imperativa como o C 
envolve o manuseio de dados 
através de variáveis
� Uma variável, na verdade, é uma 
região de memória específica 
para guardar um determinado 
dado
Introdução
#include <stdio.h>
int a;
int b[5];
main(){
a = 6;
b[0] = 10;
b[4] = 25;
... 
... ...
501 6
502 10
503
504
505
506 25
507
... ...
Introdução
� Toda variável possui um endereço de memória 
associado. Esse endereço é o local onde a variável está
armazenada em memória.
... ...
501 6
502 10
503
504
505
506 25
507
... ...
Endereço da variável a: 501
Endereço da variável b: 502
Endereço da variável b[0] = 502
Endereço da variável b[3] = 505
Endereço da variável b[4] = 506
Ponteiros
� Variáveis em geral guardam determinados tipos de 
conteúdo específicos (inteiro, ponto flutuante, 
caracter…)
� Um ponteiro é uma variável que contém um endereço 
de memória.
� Esse endereço de memória é geralmente a posição de 
uma outra variável na memória.
� Se uma variável contém o endereço de uma outra, 
então diz-se que a primeira variável aponta para a 
segunda (por isso o nome Ponteiro!)
Tipo de base * Nome da variável ;
O tipo de base é importante para a Aritmética de Ponteiros
Ponteiros - Declaração
Declaração de 
variável:
Declaração de 
ponteiro:
int x;
float j;
char v;
...
int * x;
float * j;
char * v;
...
Ponteiros
... ...
501 506
502
503
504
505
506 12
507
... ...
Neste caso:
Se a variável da posição 501 não 
for ponteiro, então possui valor 
506.
Se for ponteiro, então é do tipo 
inteiro e aponta para a posição 
506(que contém o valor 12).
Ponteiros - Operadores
Existem 2 operadores especiais para ponteiros:
� &
� *
O ‘&’ é um operador unário(ou seja, requer apenas um 
operando), que devolve o endereço na memória de seu 
operando.
O ‘*’ é o complemento do ‘&’: É um operador unário que 
devolve o valor da variável localizada no endereço que 
o segue.
Ponteiros - Operadores
Um exemplo do uso do operador & para extrair o 
endereço de uma variável é a função scanf
int numero;
scanf(“%d”, &numero); 
/* Isso quer dizer: armazene o valor lido no teclado na 
variável cujo endereço eu estou lhe fornecendo */
Ponteiros - Operadores
... ...
501
502
503
504
505
506
507
... ...
#include <stdio.h>
int var1;
int *pont1;
main(){
var1 = 6;
pont1 = &var1;
*pont1 = 30;
... 
Exemplo:
Ponteiros - Operadores
... ...
501 6
502
503
504
505
506
507
... ...
#include <stdio.h>
int var1;
int *pont1;
main(){
var1 = 6;
pont1 = &var1;
*pont1 = 30;
... 
Exemplo:
Ponteiros - Operadores
... ...
501 6
502 501
503
504
505
506
507
... ...
#include <stdio.h>
int var1;
int *pont1;
main(){
var1 = 6;
pont1 = &var1;
*pont1 = 30;
... 
Exemplo:
Ponteiros - Operadores
... ...
501 30
502 501
503
504
505
506
507
... ...
#include <stdio.h>
int var1;
int *pont1;
main(){
var1 = 6;
pont1 = &var1;
*pont1 = 30;
... 
Exemplo:
Ponteiros - Operadores
#include <stdio.h>
main() {
float var0;
int var1;
int *pont1, *pont2;
pont1 = & var1;
pont2 = & var0;
... 
Exemplo de erro:
pont2 é um ponteiro para 
inteiro e var0 é float -
ERRO DE COMPILAÇÃO
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
... ...
501
502
503
504
505
506
507
... ...
Exemplo:
main(){
int a = 8, b = 98;
int *p1, *p2;
p1 = &a;
p2 = &b;
p1 = p2;
...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
... ...
501 8
502
503
504
505
506
507
... ...
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
... ...
501 8
502 98
503
504
505
506
507
... ...
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
... ...
501 8
502 98
503
504
505
506
507
... ...
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
... ...
501 8
502 98
503 501
504
505
506
507
... ...
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
... ...
501 8
502 98
503 501
504 502
505
506
507
... ...
Ponteiros - Atribuição
Ponteiros podem ser atribuídos como uma variável 
qualquer:
int a = 8, b = 98;
int *p1, *p2;
main(){
p1 = &a;
p2 = &b;
p1 = p2;
...
... ...
501 8
502 98
503 502
504 502
505
506
507
... ...
... ...
501 8
502 98
503 502
504 502
505
506
507
... ...
É importante notar que 
mesmo que declaremos 
uma variável após a outra, 
não existe garantia da 
posição em que elas 
estarão na memória. Isto 
está a cargo do 
compilador.
Ponteiros - Atribuição
Ponteiros - Atribuição
� Outra coisa importantíssima de se lembrar 
quando usamos ponteiros é que sempre 
devemos inicializá-los de antemão. Se 
usarmos ponteiros não inicializados, 
podemos acabar acessando posições de 
memória que já estão sendo usadas por 
nosso programa ou que estão protegidaspelo sistema operacional.
� Isso pode resultar em telas como essa:
Ponteiros - Atribuição
Aritmética de Ponteiros
• Existem apenas duas operações aritméticas que podem ser 
usadas com ponteiros: adição e subtração.
• A aritmética de ponteiros é relativa ao seu tipo base, ou seja, 
depende de quantos bytes o tipo ocupa na memória.
Exemplo:
Suponhamos que pont1 esteja apontando para a posição 1000.
Após realizar um pont1++ ele passa a apontar para a posição 
1004*
* Obs.: Atualmente inteiros ocupam 4 bytes de memória!
Aritmética de Ponteiros
• Manipular ponteiros dessa forma pode ser útil, principalmente 
quando estamos tratando de arrays.
• É importante notar que o nome de um array (sem um índice) já
representa o endereço do primeiro elemento do array.
int array_int[5] = {1,2,3,4,5};
float array_float[3] = {1.0,2.3,5.1};
int *p_int = array_int;
float *p_float = array_float;
...
Aritmética de Ponteiros
• Os exemplos a seguir demonstram como é possível manipular 
arrays apenas usando ponteiros.
printf (“%d” , *p_int); // imprime 1, o primeiro elemento do array
printf (“%d” , *(p_int + 1) ); // imprime o 2 o segundo elemento
printf(“%d” , p_int[0] ); // equivalente a *p_int
printf(“%d” , p_int[1] ); // equivalente a *(p_int + 1)
printf(“%f” , *(p_float + 2); // imprime 5.1 *(p_int + 1)
// e agora prestem atenção
printf(“%f” , *(p_float + 12) );
/* note que como nos arrays, podemos “desrespeitar” o tamanho 
usando essa construção * /
...
O ponteiro NULL
• Como já foi dito antes, quando declaramos uma 
variável em C ela começa com valores aleatórios 
(lixo). Para tentar impedir que nossos ponteiros 
sejam usados de maneira danosa para o nosso 
programa, é uma convenção comum em C usar o 
identificador NULL, definido na biblioteca stdlib.h .
• Na realidade o NULL é equivalente a 0. Isso facilita 
testar nossos ponteiros, visto que se ele for NULL ele 
será avaliado como falso em um teste.
O ponteiro NULL
/* Prestem atenção no próximo exemplo, primeiro declaramos dois 
ponteiros para char */
char *pont = NULL,*pont2 = NULL;
char string[100], string2[100];
int escolha = 0;
scanf(“%1d %s”,&escolha,string); //lemos um dígito e uma string
if (escolha != 0) //se o dígito for diferente de 0...
pont = string; // apontamos para a string
scanf(“%1d %s”,&escolha,string2); 
if (escolha != 0)
pont2= string2;
O ponteiro NULL
if (pont != NULL) //testa se já atribuímos pont
printf(“Primeira string: %s” , pont); /* observem que isso irá imprimir a 
variável string, já que pont contém o endereço dela */
if (pont2) // esse teste equivale a pont2 != NULL
printf(“Segunda string: %s” , pont2);
• Como podemos ver, o ponteiro NULL é muito útil 
para evitar erros comuns, decorrentes da não 
inicialização de ponteiros e afins.
Exercícios 
• Faça uma função que recebe uma string e um 
caractere, e retorna um ponteiro para a primeira 
ocorrência do caractere na string, ou NULL caso não 
o encontre.
DICA 1: Se um função deve retornar um ponteiro, ela 
tem que ser declarada da seguinte forma:
tipo* funcao(parametros)
DICA 2: Não se esqueçam que o ‘\0’ é o caractere 
terminador da string.
char * acha_char(char *string, char a) {
char *pont = NULL;
int achou = 0;
while(*string != '\0' && achou == 0) {
if (*string == a) //testa o caractere atual
{ 
pont = string;
achou = 1;
}
else string++;
}
return pont;
}
Resposta
Resposta
int main()
{
char *string = "Lucas Fialho Zawacki";
printf("%s\n", acha_char(string, 'F'));
/* imprime “Fialho Zawacki” */
}
Indireção Múltipla
• Variáveis do tipo ponteiro, também podem apontar 
para outros ponteiros. 
• Para cada novo * na declaração da variável, 
estamos adicionando mais um nível de “indireção”.
• Um exemplo bem simples seria:
int num = 30, *p, **q;
p = &num;
q = &p;
... ...
501 30
502
503
504
505
506
507
... ...
Indireção Múltipla
int num = 30, *p, **q;
p = &num;
q = &p;
... ...
501 30
502
503
504
505
506
507
... ...
Indireção Múltipla
int num = 30, *p, **q;
p = &num;
q = &p;
... ...
501 30
502 501
503
504
505
506
507
... ...
Indireção Múltipla
int num = 30, *p, **q;
p = &num;
q = &p;
... ...
501 30
502 501
503 502
504
505
506
507
... ...
Indireção Múltipla
Indireção Múltipla
• Usar mais do que um nível de ponteiros 
pode ser útil para manipular estruturas mais 
complexas como matrizes multidimensionais, 
embora seja mais recomendado utilizar a 
notação de array.
Ponteiros void
• Qualquer tipo de ponteiro pode ser convertido para 
o tipo (void*) e depois convertido de volta para o seu 
tipo, sem que haja perda de dados.
• Esse tipo de operação será usada, principalmente 
para alocar memória dinamicamente.
Alocação Dinâmica de Memória
• Existem momentos em nossos programas, em que 
precisaremos requisitar memória em tempo de 
execução, por exemplo:
• A criação de uma matriz cujo tamanho é
fornecido pelo usuário.
• A criação de listas com tamanho indefinido.
• A biblioteca stdlib.h nos oferece algumas funções 
para nos facilitar o gerenciamento dessas 
necessidades.
Alocação Dinâmica de Memória
• A função malloc será usada para alocar uma 
quantidade ‘n’ de variáveis de algum tipo.
• Seu protótipo é:
void * malloc (unsigned int num);
float *pont_f;
pont_f = (float*) malloc(sizeof(float) * 30) ;
// alocamos um array de 30 floats
Alocação Dinâmica de Memória
• Aspectos importantes do exemplo anterior:
• A função sizeof(tipo) nos retorna o tamanho em 
bytes do tipo usado como argumento. Ela nos 
será útil para que não precisemos saber o 
tamanho de cada tipo (até porque eles podem 
variar de um computador para outro).
• O ponteiro retornado é do tipo void*, então é
necessário fazer uma conversão para o tipo que 
nós iremos usar.
Alocação Dinâmica de Memória
• Podemos manipular o ponteiro resultante como 
preferirmos, ou seja, usando a notação de arrays ou 
a de ponteiros. 
int i;
for (i = 0; i < 30; i++)
printf(“%f - ” , pont_f[i]);
// imprimimos todos elementos do array
Alocação Dinâmica de Memória
• A função free é usada para liberar a mémoria que 
nós alocamos previamente em nosso programa.
• O protótipo da função é:
free (void* ptr);
free(pont_f);
// qual a importância dessa operação?
Alocação Dinâmica de Memória
• É importante liberar a memória que alocamos 
dinamicamente porque, caso não o façamos, ela 
ficará indisponível para nós até o fim do programa.
Exercício
Crie um programa com a seguinte definição:
O programa deve ter, além da main, uma outra
função void chamada DEVOLVE_PONTEIRO que
recebe um array de inteiros e o tamanho do array e
escreve na tela o maior valor contido nesse array.
Ex.:
Temos o array de tamanho 3 com os valores:
2, 4 e 5;
DEVOLVE_PONTEIRO deve imprimir 5 na tela! 
Ex: void devolve_ponteiro(int *vet, int tam);
Ex. de chamada na main:
int vetor[3] = {1,2,3} , tam = 3;
devolve_ponteiro(vetor, 3);
USAR FOR PARA ACHAR O MAIOR VALOR!

Outros materiais