A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

CES-10 INTRODUÇÃO À COMPUTAÇÃO

Apresentações semelhantes


Apresentação em tema: "CES-10 INTRODUÇÃO À COMPUTAÇÃO"— Transcrição da apresentação:

1 CES-10 INTRODUÇÃO À COMPUTAÇÃO
Capítulo IX Ponteiros

2 Capítulo IX – Ponteiros
9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

3 9.1 – Introdução 9.1.1 – Constantes e variáveis do tipo ponteiro
As variáveis dos programas apresentados nos capítulos anteriores são usadas para guardar e manipular valores de determinados tipos Endereços também podem ser manipulados em C Sendo a uma variável declarada em um programa, &a é seu endereço Ponteiros são endereços

4 Assim como existem constantes e variáveis do tipo
int, float, char, cadeias de caracteres, vetores, matrizes e estruturas também existem constantes e variáveis do tipo ponteiro O endereço de uma variável a declarada num bloco qualquer permanece o mesmo durante a execução do bloco Então &a é uma constante do tipo ponteiro Variável do tipo ponteiro armazena um endereço que pode ser alterado durante a execução do programa

5 Variáveis-ponteiros podem guardar endereços de outras variáveis
Diz-se que elas apontam para essas outras variáveis Na declaração de uma variável-ponteiro, deve-se especificar o tipo das variáveis para as quais ela pode apontar Exemplo: na declaração float *p; p é uma variável-ponteiro destinada a guardar endereços de variáveis do tipo float, ou a apontar para elas Abreviadamente, p é um ponteiro para o tipo float

6 Exemplo: seja trecho de programa:
Resultado int c = 237, b = 15, *q; double a = 13.5, *p; p = &a; q = &b; printf ("Endereco(p) = %d\n", &p); printf (" p = %d\n", p); printf ("Endereco(a) = %d\n", &a); printf ("Endereco(q) = %d\n", &q); printf (" q = %d\n", q); printf ("Endereco(b) = %d\n", &b); printf ("Endereco(c) = %d\n", &c); printf (" a = %g\n", a); printf (" b = %d\n", b); printf (" c = %d\n", c); Endereco(p) = p = Endereco(a) = Endereco(q) = q = Endereco(b) = Endereco(c) = a = 13.5 b = 15 c = 237 Com este resultado, pode-se desenhar o mapa da memória a seguir

7 13.5 15 237 int c = 237, b = 15, *q; double a = 13.5, *p; 1638204
p = &a; q = &b; p a q b c 13.5 15 237 Endereco(p) = p = Endereco(a) = Endereco(q) = q = Endereco(b) = Endereco(c) = a = 13.5 b = 15 c = 237 Resultado

8 13.5 15 237 int c = 237, b = 15, *q; double a = 13.5, *p; 1638204
p = &a; q = &b; p a q b c 13.5 15 237 &a é uma constante-ponteiro para double &b é uma constante-ponteiro para int

9 13.5 15 237 int c = 237, b = 15, *q; double a = 13.5, *p; 1638204
p = &a; q = &b; p a q b c 13.5 15 237 q é um ponteiro para o tipo int p é um ponteiro para o tipo double p recebe o endereço de a q recebe o endereço de b p aponta para a q aponta para b a é apontada por p b é apontada por q

10 13.5 15 237 int c = 237, b = 15, *q; double a = 13.5, *p; 1638204
p = &a; q = &b; p a q b c 13.5 15 237 Endereços, isto é ponteiros, ocupam 4 bytes Não é recomendável fazer: p = &b , pois b é um int e p é um ponteiro para o tipo double Alguns compiladores não aceitam isso

11 13.5 15 237 int c = 237, b = 15, *q; double a = 13.5, *p;
p = &a; q = &b; p a q b c 13.5 15 237 Duas formas de representação gráfica: ou simplesmente: 13.5 a p 15 b q 13.5 a p 15 b q

12 Endereços são números inteiros não-negativos
Então, esses números podem ser atribuídos às variáveis ponteiros, desde que sejam convertidos para endereços usando-se fator de conversão Exemplo: seja a declaração double *p; muitos compiladores não permitem p = 48237; O lado esquerdo deveria receber um endereço e não um inteiro No entanto, a seguinte atribuição é aceita: p = (double *) 48237; O inteiro é convertido no endereço 48237

13 Exemplo: pelas declarações double *p; int *q;
Muitos compiladores também não aceitam atribuição entre ponteiros de tipos diferentes Exemplo: pelas declarações double *p; int *q; muitos compiladores não aceitam p = q; nem q = p; É necessário fazer p = (double *)q; e q = (int *)p; Se alguns compiladores aceitam certas irregularidades, mas outros não, para melhorar portabilidade, é bom não cometê-las A palavra ponteiro poderá ser usada tanto para variáveis como para valores do tipo ponteiro

14 Em C há uma constante simbólica para ele: NULL
Usando ponteiros, o endereço zero de memória é considerado de forma muito especial Em C há uma constante simbólica para ele: NULL As seguintes atribuições são equivalentes: p = 0; e p = NULL; Diz-se que p está aterrado, ou então que aponta para lugar nenhum É diferente de dizer que p está indefinido, pois tal lugar é perfeitamente definido Aqui, lugar nenhum é diferente de nenhum lugar

15 Representações gráficas para o aterramento de ponteiros:
p NULL p

16 9.1.2 – Acesso ao local apontado por um ponteiro
Seja a declaração: int a, b, *p; O local apontado por p é referenciado por *p Executando-se p = &a; então *p passa a coincidir com a Depois, executando-se p = &b; então *p passa a coincidir com b Seja a declaração int a, *p = &a; p a *p b *p Correto: p é ponteiro inicializado com o endereço de a É errado dizer: local apontado por p recebe o endereço de a

17 Exemplo: Seja o seguinte trecho de programa: int a, b = 2, *p;
p = &a; *p = 1; b = *p; Prosseguindo Inicialmente a b p 1 1 2

18 Exemplo: Seja a seguinte declaração:
int a = 2, b = 5, *p = &a, *q = &b; Voltando à situação inicial: Fazendo *p = *q; Inicialmente: Fazendo p = q; a p 5 2 b q 5 Apesar dos conteúdos de *p e *q serem iguais, o conteúdo de p é diferente do conteúdo de q (*p == *q) e (p ≠ q)

19 Região protegida pelo sistema operacional
Exemplo: Seja o seguinte trecho de programa: int *p, a; p = (int *)134; a = *p; printf ("*p = %d", a); 134 p Região protegida pelo sistema operacional Erro de execução: O endereço 134 é protegido pelo sistema operacional O comando a = *p tenta copiar o valor ali guardado a RAM

20 O endereço zero também é protegido pelo sistema operacional
Portanto, ao se aterrar um ponteiro, a simples referência ao local apontado por ele gera o mesmo tipo de erro Então a sequência de comandos p = NULL; a = *p; não pode ser usada

21 Sejam p e q dois ponteiros quaisquer
A divisão entre os conteúdos dos locais apontados por eles não pode ser expressa por *p/*q A sequência de caracteres “/*” inicia um comentário Deve-se deixar pelo menos um espaço em branco no meio dessa sequência: *p/ *q Nos atuais ambientes de programação esse problema é facilmente detectado Ali os comentários são escritos com tipo e coloração das letras distintos do resto do texto dos programas Em ambientes mais antigos, isso já causou muitos atrasos na programação

22 As principais utilidades dos ponteiros são:
Alocação dinâmica de variáveis indexadas Passagem por referência de argumentos a parâmetros Encadeamento de estruturas Os dois primeiros itens eram realizados não por intermédio de ponteiros nas linguagens de programação antes de C Para o terceiro sim, tais linguagens já usavam ponteiros Aliás, o encadeamento de estruturas foi a principal razão para a criação de ponteiros Ele é abordado no último tópico deste capítulo e usado intensamente em Estruturas de Dados

23 Capítulo IX – Ponteiros
9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

24 9.2 – Relação entre Ponteiros e Variáveis Indexadas
9.2.1 – O ponteiro-nome de variável indexada Em C, diferentemente das linguagens anteriores, há uma forte relação entre ponteiros e variáveis indexadas O nome de uma variável indexada é o endereço do primeiro de seus elementos É uma constante-ponteiro apontando para seu elemento zero Não tem um local exclusivo na memória

25 O ponteiro-nome de variável indexada aponta para um local fixo (elemento de índice zero)
Então ele tem valor constante durante a execução do programa (ponteiro de valor fixo) Não pode ser alterado como um ponteiro comum Seja a declaração int A[8]; Representação gráfica de A:

26 int A[8]; O nome A não tem local exclusivo; &A é o endereço do início do vetor A na memória O valor de A (ou seja, A, simplesmente) é o endereço de A[0] (&A[0]) A escrita do valor do local apontado por A (ou seja, de *A) resulta no conteúdo de A[0] O nome de uma variável indexada pode ser atribuído a um ponteiro de mesmo tipo

27 Exemplo: seja o seguinte trecho de programa: int i, A[8], B[5], *p;
p = A; p = B; Proibidos: A = p; B = p; A = B; B = A; A = &i; B = &i; p tem local exclusivo A e B não têm Após p = A; Após p = B; Inicialmente: A A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] p ? p tornou-se equivalente a A: p[0]  A[0], p[1]  A[1], ... , p[7]  A[7] p tornou-se equivalente a B: p[0]  B[0], p[1]  B[1], ... , p[4]  B[4] B B[0] B[1] B[2] B[3] B[4] *A  A[0] e *B  B[0] p se tornou variável indexada

28 9.2.2 – Aritmética de endereços e ponteiros
Seja a seguinte declaração: int *p, i; A expressão p+i é o endereço do iésimo inteiro após o inteiro apontado por p (p+i = &p[i]) Seja a seguinte declaração: int A[10], i; Analogamente, A+i = &A[i] e *(A+i)  A[i] p[0] p[1] p[i] p *p *(p+1) *(p+i) A[0] A[1] A[i] A *A *(A+1) *(A+i)

29 Exemplo: seja o seguinte trecho de programa:
double *p, *q, *r, A[3]; p = A; q = p+1; r = p+2; printf ("p = %d; &A[0] = %d;", p, &A[0]); printf ("\nq = %d; &A[1] = %d;", q, &A[1]); printf ("\nr = %d; &A[2] = %d;", r, &A[2]); printf ("\n\nq-p = %d;\nr-p = %d;", q-p, r-p); printf("\n\nender(q)-ender(p) = %d;\nender(r)-ender(p) = %d;", (int)q-(int)p, (int)r-(int)p); A[0] A[1] A[2] p q r p = ; &A[0] = ; q = ; &A[1] = ; r = ; &A[2] = ; q-p = 1; r-p = 2; ender(q)-ender(p) = 8; ender(r)-ender(p) = 16; Diferenças de endereços Diferenças de índices No vídeo

30 Por exemplo, considerando-se a seguinte declaração:
Relações entre ponteiros e variáveis indexadas e entre subscritos e o operador unário ‘*’ possibilitam várias alternativas para realizar certas operações Por exemplo, considerando-se a seguinte declaração: int i, A[10] = {1,2,3,4,5,6,7,8,9,10}, *p, soma; A soma dos elementos de A pode ser feita por: for (soma = 0, i = 0; i < 10; i++) soma += A[i]; for (soma = 0, i = 0; i < 10; i++) soma += *(A+i); for (soma = 0, p = A; p < &A[10]; p++) soma += *p; for (soma = 0, p = A, i = 0; i < 10; i++) soma += p[i]; for (soma = 0,p = A,i = 0; i < 10; i++) soma += *(p+i);


Carregar ppt "CES-10 INTRODUÇÃO À COMPUTAÇÃO"

Apresentações semelhantes


Anúncios Google