Introduo a Ponteiros ou Apontadores Crditos Profa Karla

  • Slides: 36
Download presentation
Introdução a Ponteiros ou Apontadores Créditos: Profa. Karla de Souza - UFTPR Modificada por

Introdução a Ponteiros ou Apontadores Créditos: Profa. Karla de Souza - UFTPR Modificada por Prof. Marcus Salerno http: //www. dainf. ct. utfpr. edu. br/~karla/ Disciplina IF 65 A

Por que Estudar Ponteiros? • É praticamente impossível desenvolver um programa com algum grau

Por que Estudar Ponteiros? • É praticamente impossível desenvolver um programa com algum grau de complexidade ou tamanho significativo em C e C++ sem o uso de apontadores. • C é altamente dependente de ponteiros • Portanto, para ser um bom programador C, é preciso conhecê-los • Mas. . . O uso descuidado de ponteiros pode levar a sérios bugs e a dores de cabeça terríveis : -).

E o que são Ponteiros ou Apontadores? • Os ints guardam inteiros. • Os

E o que são Ponteiros ou Apontadores? • Os ints guardam inteiros. • Os floats guardam números de ponto flutuante. • Os chars guardam caracteres. • Ponteiros guardam endereços de memória

Ponteiros em Linguagem C • Um ponteiro também tem tipo. • Em C quando

Ponteiros em Linguagem C • Um ponteiro também tem tipo. • Em C quando declaramos ponteiros nós informamos ao compilador para que tipo de variável vamos apontá-lo. • Um ponteiro int aponta para um inteiro, isto é, guarda o endereço de um inteiro.

Como Usar Ponteiros • Para declarar: tipo_do_ponteiro *nome_da_variável; • É o asterisco (*) que

Como Usar Ponteiros • Para declarar: tipo_do_ponteiro *nome_da_variável; • É o asterisco (*) que faz o compilador saber que aquela variável não vai guardar um valor mas sim um endereço para aquele tipo especificado. • Exemplos: – int *pt; – char *temp, *pt 2;

Como Usar Ponteiros • char *temp, *pt 2; • Estas variáveis foram declaradas, mas

Como Usar Ponteiros • char *temp, *pt 2; • Estas variáveis foram declaradas, mas não inicializadas. • Ou seja, estes ponteiros apontam para um endereço indefinido. • Este endereço pode ser, por exemplo, uma porção de memória reservada ao sistema operacional • Usar um ponteiro sem inicializá-lo pode causar travamento do computador, ou algo pior!

Como Usar Ponteiros • Para inicializar um ponteiro podemos igualá-lo a um valor de

Como Usar Ponteiros • Para inicializar um ponteiro podemos igualá-lo a um valor de memória. • Mas, como saber a posição na memória de uma variável do nosso programa? • Seria muito difícil saber o endereço de cada variável que usamos, mesmo porque estes endereços são determinados pelo compilador na hora da compilação e realocados na execução. • Podemos então deixar que o compilador faça este trabalho por nós. Para saber o endereço de uma variável basta usar o operador &. • Exemplo: – float num = 2. 5; – float *pt; – pt = #

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5 ?

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5 ? Compilador aloca um endereço qualquer disponível

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5

Como Usar Ponteiros float num = 2. 5; Variável Valor Endereço num 2. 5 1000 Compilador aloca um endereço qualquer disponível num Memória 2. 5 1000 1001 1002 1003

Como Usar Ponteiros float num = 2. 5; float *pt; Variável Valor Endereço num

Como Usar Ponteiros float num = 2. 5; float *pt; Variável Valor Endereço num 2. 5 1000 pt ? ? num Memória 2. 5 1000 1001 1002 1003

Como Usar Ponteiros float num = 2. 5; float *pt; Memória Variável Valor Endereço

Como Usar Ponteiros float num = 2. 5; float *pt; Memória Variável Valor Endereço num 2. 5 1000 pt ? 1001 num pt 2. 5 ? 1000 1001 1002 Também feito pelo compilador, não necessariamente na posição seguinte. 1003

Como Usar Ponteiros float num = 2. 5; float *pt; pt=# Qual valor terá

Como Usar Ponteiros float num = 2. 5; float *pt; pt=# Qual valor terá a variável pt? Memória Variável Valor Endereço num 2. 5 1000 pt ? 1001 num pt 2. 5 ? 1000 1001 1002 1003

Como Usar Ponteiros float num = 2. 5; float *pt; pt=# O endereço da

Como Usar Ponteiros float num = 2. 5; float *pt; pt=# O endereço da variável num! Memória Variável Valor Endereço num 2. 5 1000 pt 1000 1001 num pt 2. 5 1000 1001 1002 1003

Como Usar Ponteiros • Criamos um float com o valor 2. 5 e um

Como Usar Ponteiros • Criamos um float com o valor 2. 5 e um apontador para um float identificado como pt. • A expressão &num nos dá o endereço de num, o qual armazenamos em pt. • Agora que pt tem o endereço de num, podemos também alterar o valor de num usando pt.

Como Usar Ponteiros • Para tanto vamos usar o operador "inverso" do operador &:

Como Usar Ponteiros • Para tanto vamos usar o operador "inverso" do operador &: – É o próprio operador *. • No exemplo acima, uma vez que fizemos pt=&num a expressão *pt é equivalente ao próprio num. • Isto significa que, se quisermos mudar o valor de num para 3. 5, basta fazer *pt=3. 5.

Exemplo 1 // Programa que exemplifica o uso de ponteiros. int main () {

Exemplo 1 // Programa que exemplifica o uso de ponteiros. int main () { float num, valor; float *pt; num=2. 5; pt=# valor=*pt; // Pega o endereço de num. // Atribuído a valor de maneira indireta printf ("n%fn", valor); printf ("Endereco para onde o ponteiro aponta: %p n", pt); printf ("Valor da variavel apontada: %f n", *pt); system("PAUSE"); return(0); } Especificador de formato para ponteiro

Exemplo 2 // Outro exemplo para ponteiros. int main () { float num, *pt;

Exemplo 2 // Outro exemplo para ponteiros. int main () { float num, *pt; num= 2. 5; pt= # // Pega o endereco de num printf ("n. Valor inicial: %f n", num); *pt=3. 5; // Muda o valor de num de uma maneira indireta printf ("n. Valor final: %f n", num); system("PAUSE"); return(0); }

 • Exemplos: • Variáveis e Apontadores. cpp • ap_x. c • Operações com

• Exemplos: • Variáveis e Apontadores. cpp • ap_x. c • Operações com Apontador. cpp • http: //www. youtube. com/watch? v=6 pm. Wojis. M_E&feature=pl ayer_embedded

Exercício • Procure determinar quais valores são impressos ao final destes programas. Confira sua

Exercício • Procure determinar quais valores são impressos ao final destes programas. Confira sua resposta testando o programa. #include <stdio. h> #include <stdlib. h> int main() { int a, b, *c; a = 4; b = 3; c = &a; *c = *c + 1; c = &b; b = b+4; printf("%d %d %d", a, b, *c); system(“PAUSE”); return 0; } #include <stdio. h> #include <stdlib. h> int main() { int a, b, *c, *d, *f; a = 4; b = 3; c = &a; d = &b; *c = *c / 2; f = c; c = d; d = f; printf("%d %d", *c, *d); system(“PAUSE”); return 0; }

Ponteiros e Vetores • Vetores (inclusive strings) e matrizes já são, por definição, ponteiros.

Ponteiros e Vetores • Vetores (inclusive strings) e matrizes já são, por definição, ponteiros. • Por exemplo, uma string pode ser declarada também da seguinte forma: char *s = "Programacao"; • O compilador irá criar a variável s, com tipo apontador de caractere e inicializá-la com o endereço do byte que armazena o primeiro “P". • Repare que a declaração "char s[]" é equivalente a "char *s".

Onde Usar Ponteiros? • Funções – Passagem de parâmetros por referência • Alocação Dinâmica

Onde Usar Ponteiros? • Funções – Passagem de parâmetros por referência • Alocação Dinâmica – Não sei o tamanho que o vetor precisa ter…. – Não sei o tamanho que cada string precisa ter… – Não sei o tamanho que a matriz precisa ter…

Onde Usar Ponteiros? • Funções – Passagem de parâmetros por referência • Alocação Dinâmica

Onde Usar Ponteiros? • Funções – Passagem de parâmetros por referência • Alocação Dinâmica – Não sei o tamanho que o vetor precisa ter…. – Não sei o tamanho que cada string precisa ter… – Não sei o tamanho que a matriz precisa ter…

Passagem de Parâmetros Por Valor e por Referência

Passagem de Parâmetros Por Valor e por Referência

Passagem por Valor • Quando chamamos uma função os valores dos parâmetros passados são

Passagem por Valor • Quando chamamos uma função os valores dos parâmetros passados são copiados para os parâmetros ‘formais’ da função. • Isto quer dizer que não são alterados os valores que os parâmetros têm fora da função. • Este tipo de chamada de função é denominado chamada por valor. • Isto ocorre porque são passados para a função apenas os valores dos parâmetros e não os próprios parâmetros.

Passagem por Valor int main() { int x, y; // Declaração de funções. void

Passagem por Valor int main() { int x, y; // Declaração de funções. void troca(int, int); // Chama função para trocar valores. x=5; y=6; troca(x, y); printf("O valor de x agora eh %d e o de y eh %d n", x, y); system("PAUSE"); } void troca(int a, int b) { int temp; temp = a; a = b; b = temp; }

Passagem por Valor • Funcionou? Por que? • As variáveis a e b da

Passagem por Valor • Funcionou? Por que? • As variáveis a e b da função troca sofrem alterações dentro da função, mas as variáveis a e b da main não. • É a passagem por valor. • Somente os valores são copiados, não havendo alteração nas variáveis.

Passagem por Referência • Outro tipo de passagem de parâmetros para uma função ocorre

Passagem por Referência • Outro tipo de passagem de parâmetros para uma função ocorre quando as alterações nos parâmetros dentro da função (chamados parâmetros formais) alteram os valores dos parâmetros que foram passados para a função. • Este tipo de passagem de parâmetro tem o nome de “passagem por referência". • Este nome vem do fato de que, neste tipo de chamada, não se passa para a função os valores das variáveis, mas sim suas referências (ou endereços): – a função usa as referências para alterar os valores das variáveis fora da função.

Passagem por Referência • Quando queremos alterar as variáveis que são passadas para uma

Passagem por Referência • Quando queremos alterar as variáveis que são passadas para uma função, nós podemos declarar seus parâmetros como sendo apontadores. • Os apontadores são a "referência" que precisamos para poder alterar a variável fora da função. • O único inconveniente é que, quando usarmos a função, teremos de lembrar de colocar um & na frente das variáveis que estivermos passando para a função.

Passagem por Referência // Declaração de funções. void troca(int *, int *); int main()

Passagem por Referência // Declaração de funções. void troca(int *, int *); int main() { int x, y; void troca(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } // Chama função para trocar valores x=5; Declara os parâmetros da função como ponteiros y=6; troca(&x, &y); printf("O valor de x agora eh %d e o de y eh %d n", x, y); Passa os endereços das variáveis system("PAUSE"); } Ver troca de estruturas em: troca_struct. c

Passagem por Referência • Funcionou agora? Por que? • Lembra da função scanf()? Das

Passagem por Referência • Funcionou agora? Por que? • Lembra da função scanf()? Das variáveis precedidas por &? • Por que a função scanf() precisa usar a chamada por referência? • Para alterar o valor das variáveis que passamos para ela!

Exercício 1 • Escreva uma função que receba duas variáveis inteiras e "zere" o

Exercício 1 • Escreva uma função que receba duas variáveis inteiras e "zere" o valor das variáveis. – Na função principal, declare e inicie as variáveis inteiras com qualquer valor, chame a função para zerá-los e imprima os valores finais. – Use o que você aprendeu para fazer a implementação. – Teste a passagem por valor e por referência no programa.

Exercício 2 • Seja a função troca cujo protótipo está definido abaixo, uma função

Exercício 2 • Seja a função troca cujo protótipo está definido abaixo, uma função que permute o valor de uma variável do tipo double por outra, ambas passadas por referência. – Defina uma função main que permute os valores das variáveis a, b e c, declaradas abaixo, de forma que no final a<=b<=c. A função main deve chamar a função troca. • void troca(double *x, double *y)

Resumo • O que é um ponteiro? – É uma variável que armazena o

Resumo • O que é um ponteiro? – É uma variável que armazena o endereço na memória do computador onde está outra variável • Operadores relacionados a ponteiros: * (asterisco): informa que uma variável irá armazenar o endereço de outra variável (que a variável é um ponteiro), ou informa ao computador que você deseja o valor que está no endereço armazenado; & (e comercial): retorna o endereço de uma variável;

Resumo • operador * – declara-se um ponteiro com * • int *x; –

Resumo • operador * – declara-se um ponteiro com * • int *x; – acessa-se (alterar, modificar, ler) o valor da variável apontada também com * • *x = 10; // atribui o valor 10 ao local apontado pelo ponteiro ‘x’ • printf(“%d”, *x); // imprime valor armazenado no local apontado por ‘x’ – observação: strings, vetores e matrizes funcionam de forma diferente: um vetor, string ou matriz é um ponteiro por definição • operador & – acessa (alterar, modificar, ler) o endereço de uma variável (que é um ponteiro)

Resumo • Passagem de Parâmetro por Valor – É a passagem de parâmetro ‘default’

Resumo • Passagem de Parâmetro por Valor – É a passagem de parâmetro ‘default’ da linguagem C. Se nada é especificado, somente os valores dos parâmetros passados são copiados para os parâmetros formais da função • Passagem de Parâmetro por Referência – É a passagem de parâmetro usando ponteiros. Desta forma os endereços das variáveis é que são passados à função e todas as alterações feitas nas variáveis passadas por parâmetro permanecem após o fim da função. • Declaração: void troca (int *a, int *b); • Chamada da função: troca (&num 1, &num 2); • Definição da função: void troca (int *a, int *b) { \ Instruções. }