aula04 ponteiros e conversao

65
Ponteiros Yuri Tavares dos Passos

Upload: yuri-passos

Post on 05-Aug-2015

68 views

Category:

Science


8 download

TRANSCRIPT

Page 1: Aula04   ponteiros e conversao

Ponteiros

Yuri Tavares dos Passos

Page 2: Aula04   ponteiros e conversao

Arquitetura de Von Neumann● Os computadores pessoais utilizam uma

arquitetura que é baseada na arquitetura de Von Neumann.

● Esta arquitetura se baseia na utilização de um mesmo bloco de memória para armazenar dados e código executável.

● O processador fica responsável por buscar código na mesma memória em que busca por um dado.

Page 3: Aula04   ponteiros e conversao

Arquitetura de Von Neumann

Busca e executa

Lê e escreve

Page 4: Aula04   ponteiros e conversao

Arquitetura de Von Neumann

Dados

Código

Código

Dados

Código

Dados

Memória Principal

Busca e executa

Lê e escreve

Page 5: Aula04   ponteiros e conversao

Arquitetura de Von Neumann● Suponha uma memória RAM com

capacidade de 8 B. Ela pode ser endereçada dos endereços 0 a 7, cada um com a capacidade de 1 B.

1 B

0x00x10x20x30x40x50x60x7

E se ela tivesse 1GB, iria doEndereço 0 a qual número decimal?

E hexadecimal?

Page 6: Aula04   ponteiros e conversao

Arquitetura de Von Neumann● Suponha uma memória RAM com

capacidade de 8 B. Ela pode ser endereçada dos endereços 0 a 7, cada um com a capacidade de 1 B.

1 B

0x00x10x20x30x40x50x60x7

E se ela tivesse 1GB, iria doEndereço 0 a qual número decimal?Resp.: 1073741823E em hexadecimal?Resp.: 3FFFFFFF

Page 7: Aula04   ponteiros e conversao

Arquitetura de Von Neumann

16

MOVE 16 0x19

SOME 0x21 0x19

3.89

MOVE 0x19 0x24

?

Memória PrincipalEndereços

0x19

0x21

0x20

0x22

0x23

0x24

Page 8: Aula04   ponteiros e conversao

Arquitetura de Von Neumann

00010000

01010101

10100010

00100111

01010101

00010000

Memória PrincipalEndereços

0x19

0x21

0x20

0x22

0x23

0x24

Page 9: Aula04   ponteiros e conversao

Arquitetura de Von Neumann

16

MOVE 16 0x19

SOME 0x21 0x19

3.89

MOVE 0x19 0x24

?

Memória PrincipalEndereços

0x19

0x21

0x20

0x22

0x23

0x24

Esta instrução envolveo uso de um endereço e um valor.

Esta instrução envolveapenas endereços.

Page 10: Aula04   ponteiros e conversao

Ponteiro

● Como manipular endereços de memória no código-fonte?– Utilizando um tipo de variável para endereços.

● Um ponteiro ou apontador é uma variável que guarda endereços de memória.

● Endereços de memória são valores inteiros que podem ser armazenados e utilizados no código.

Page 11: Aula04   ponteiros e conversao

Ponteiros

● Aplicações de ponteiros:– Estruturas de dados mais eficientes.

– Aplicações que envolvam a organização dos dados.

– Aplicações que devem ser rápidas.

– Alocação dinâmica de memória.

– Acessar variáveis que não são visíveis em uma função.

– Retornar mais de um valor para uma função.

● A tentativa de evitar o uso de ponteiros implicará quase sempre códigos maiores e de execução mais lenta.

Page 12: Aula04   ponteiros e conversao

Ponteiro

16

3.98

SOME 0x24 0x19

0x20

MOVE 0x19 0x24

0x22

0x19

0x21

0x20

0x22

0x23

0x24

São variáveis que apontam para outras

Page 13: Aula04   ponteiros e conversao

Ponteiro

● Nos exemplos acima, os endereços possuíam 1 B de tamanho.

● Quantos valores podem ser armazenados com 1 B?

Page 14: Aula04   ponteiros e conversao

Ponteiro

● Nos exemplos acima, os endereços possuíam 1 B de tamanho.

● Quantos valores podem ser armazenados com 1 B?– Resp.: 1 B = 8 b

28 = 256

● Quantos Bytes as memórias vendidas no comércio possuem?

Page 15: Aula04   ponteiros e conversao

Ponteiro

● Suponha um computador de 1 GB.● Ela pode possuir 1073741824 endereços de

1 B distintos. Para representar o maior endereço (3FFFFFFF), precisamos de 4 B.

● Portanto, para armarzenarmos um endereço numa máquina atual, precisaremos de 4 B ou mais!

Page 16: Aula04   ponteiros e conversao

Ponteiro

● Outro detalhe do exemplo de máquina apresentado é o tamanho dos nossos dados. Quantos bytes eles usam?

16

MOVE 16 0x19

SOME 0x21 0x19

3.89

MOVE 0x19 0x24

0

0x19

0x21

0x20

0x22

0x23

0x24

Page 17: Aula04   ponteiros e conversao

Ponteiro

● Qual tipo de dado em C possui 1 B?

Page 18: Aula04   ponteiros e conversao

Ponteiro

● Qual tipo de dado em C possui 1 B?● Resp.: char e unsigned char

Page 19: Aula04   ponteiros e conversao

Ponteiro

● Os tipos básicos de C possuem todos 1 B?

Page 20: Aula04   ponteiros e conversao

Tipos básicos Tamanho Precisão

char -> p/ caracteres 1 byte - 128 a + 127

int -> p/ inteiros 4 bytes* -2147483648 a 2147483647

float -> p/ reais 4 bytes* -3.4E-38 a +3.4E+38double -> p/ reais 8 bytes* -1.7E-308 a +1.7E+308

* Variam a depender do processador

Tipos de dados básicos

Page 21: Aula04   ponteiros e conversao

Ponteiro

● Considere o seguinte código:

Page 22: Aula04   ponteiros e conversao

Ponteiro

● Vamos pegar um número inteiro, como 0. Em uma célula de 4 B (= 32 b), temos como representação binária 32 zeros consecutivos.

● Um número inteiro como 1465232370 temos como representação binária 01010111010101011010101111110010– Em hexadecimal: 5755ABF2

Page 23: Aula04   ponteiros e conversao

Ponteiro

● Um caractere como 'a', na tabela de conversão ASCII é igual ao número 65. Como binário temos 01000001.– Em hexadecimal: 41

● O bloco de memória do código apresentado seria como apresentado a seguir.

Page 24: Aula04   ponteiros e conversao

Ponteiro

0xbff43513

0xbff43514

0xbff43515

0xbff43516

0xbff43517

0xbff43518

0xbff43519

0xbff4351a

0xbff4351b

00000000

00000000

00000000

00000000

01010111

01010101

10101011

11110010

01000001

} a = 0

} b = 1465232370

} c = 'a'

Page 25: Aula04   ponteiros e conversao

Ponteiro

● O endereço do inteiro a é 0xbff43513. Mas o inteiro vai de 0xbff43513 a 0xbff43516

● O endereço do caractere c é 0xbff4351b. Apenas este endereço é suficiente para guardá-lo.

● Além do endereço, o programa precisa saber o tamanho do dado que aquele endereço armazena.

Page 26: Aula04   ponteiros e conversao

Ponteiro

● Assim, um ponteiro além de armazenar o endereço de uma variável também possui o tamanho do dado daquela variável.

● Para se declarar uma variável do tipo ponteiro utiliza-se o símbolo * após o tipo de dado que este ponteiro deve apontar.

● A sintaxe de declaração é:

<tipo de dado> * <nome do ponteiro>;

Page 27: Aula04   ponteiros e conversao

Ponteiro

Page 28: Aula04   ponteiros e conversao

Ponteiro

● Para obter o endereço de memória de uma variável utiliza-se o operador &.

● A sintaxe deste operador é:

& <variável>

Page 29: Aula04   ponteiros e conversao

Ponteiro

Page 30: Aula04   ponteiros e conversao

Ponteiro

● Para acessar o conteúdo do que um ponteiro está apontando, usa-se *.

● A operação que realiza o acesso a algum dado apontado por um ponteiro é conhecida como desreferenciamento.– Um endereço de memória é uma referência a um

dado.

● Dentro de expressões, a sintaxe é:

* <variável ponteiro>

Page 31: Aula04   ponteiros e conversao

Ponteiro

Page 32: Aula04   ponteiros e conversao

Ponteiro

● Se fosse para escrever na tela os endereços onde as variáveis ponteiros pa, pb e pc estão o que deveria ser feito?

Page 33: Aula04   ponteiros e conversao

Ponteiro

Page 34: Aula04   ponteiros e conversao

Atribuições e tipos

● Em um compilador, o tipo de dado do lado esquerdo de uma atribuição deve ser igual ao tipo do resultado do lado direito.

● Exemplo 1:

c = 'b';

char char

Page 35: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 2:

a = 0 - b;

● Exemplo 3:

float f = 3.14 * 4.0 / a ;

int int

float float

Page 36: Aula04   ponteiros e conversao

Atribuições e tipos

● Quando utilizamos o operador &, o resultado é um endereço para a variável aplicada a este operador.

● Se temos:

&<variável>;

● O operador & retorna um tipo igual a “ponteiro do tipo da” <variável>.

Page 37: Aula04   ponteiros e conversao

Atribuições e tipos

● Para declaramos uma variável p1 ponteiro para o tipo caractere fazemos:

char * p1;

● Para declaramos uma variável p2 ponteiro para o tipo inteiro fazemos:

int * p2;

● Assim, podemos usar o * para denotar o tipo ponteiro de algum tipo.

Page 38: Aula04   ponteiros e conversao

Atribuições e tipos

● A regra de igualdade entre tipos nos dois lados de uma atribuição também funciona para ponteiros.

● Exemplo 1:

char c = 'a';char *p;p = &c; char* = & char

Sabendo-se que & <tipo> = <tipo>*, temos:

char* = char*

Page 39: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 2:

float f = 3.14;float *p;p = &f;

● Exemplo 3:

int b = 13;char * pi;pi = &b;

float* = & floatfloat* = float*

char* = & intchar* = int* ERRADO!

Page 40: Aula04   ponteiros e conversao

Atribuições e tipos

● Quando utilizamos o operador *, o resultado é um conteúdo para o mesmo tipo que o ponteiro deve apontar.

● Se temos:

* <variável ponteiro>;

● O operador * retorna um tipo igual ao tipo do ponteiro, sem um asterisco. Ou seja, ele remove o termo “ponteiro” para aquele tipo.

Page 41: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 1:– char c = 'b';

char d;char *p = &c;d = *p;

char = * char*Sabendo-se que * <ponteiro para tipo> = <tipo>, temos:char = char

O * em preto representa o operador desreferenciamento.

O * em vermelho representa o tipo “ponteiro de”.

Page 42: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 2:

int x = 9, y;int *p = &x;y = 2 + *p;

int = int + * int*int = int + intint = int

Qual o valor de y?

Page 43: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 3:

long l1 = 2E12;long *p1 = &l1;l1 = 2 * *p1;

long = long * * long*long = long * longlong = long

Qual o valor de l1?

Page 44: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 4:

long l1 = 2000, l2 = 0;long *p1, *p2;p1 = &l1;p2 = &l2;*p2 = 2 * *p1;

Existe algo de errado na última expressão?

Page 45: Aula04   ponteiros e conversao

Atribuições e tipos

● Exemplo 4:

long l1 = 2000, l2 = 0;long *p1, *p2;p1 = &l1;p2 = &l2;*p2 = 2 * *p1;printf(“%i\n”,l2);

Qual o valor aparecerá na tela?

Page 46: Aula04   ponteiros e conversao

Observação sobre * e &

● Observação– Os operadores & e * não podem ser apliados

a constantes.

● Exemplo:

int * p = &12;

– Isto não é possível pois a constante 12 não está armazenada em nenhum endereço.

Page 47: Aula04   ponteiros e conversao

Observação sobre * e &

● Exemplo:

char c = * 0x5623;

– Interpretando este exemplo em linguagem humana estaríamos dizendo que o valor de c será igual ao valor do byte que estiver no endereço 0x5623.

– Mas o S.O. protege este endereço, pois ele pode estar sendo utilizado por outro programa, evitando falha de segurança.

Page 48: Aula04   ponteiros e conversao

Ponteiro sem tipo

● Existe também um tipo de ponteiro que não está associado a nenhum tipo de variável: void *.

● Este tipo é utilizado quando se deseja acessar um endereço de memória ignorando o tipo de dado que existe neste endereço.

● Exemplo de declaração:

void * p;

void * bloco_de_memória;

● Contudo, atribuições para este tipo de variável necessitam de conversões explícitas para void*.

Page 49: Aula04   ponteiros e conversao

Conversão entre tipos

● Existem dois tipos de conversões– Implícitas

– Explícitas

● As conversões ímplicitas são feitas automaticamente pelo compilador, quando o tipo convertido é um subconjunto do tipo a ser atribuído.

Page 50: Aula04   ponteiros e conversao

Conversão implícita

● Exemplo:

int i = 1;float f = i;

Isto está errado?

Page 51: Aula04   ponteiros e conversao

Conversão implícita

● Exemplo:

int i = 1;float f = i;printf(“%f\n”,f);

Que valor será escrito na tela?

Page 52: Aula04   ponteiros e conversao

Conversão implícita

● Exemplo:

int i = 1;float f = i;

float int ℤ

Page 53: Aula04   ponteiros e conversao

Conversão implícita

● Exemplo:

int i = 1;float f = (float) i;

● Foi realizada uma conversão implícita de inteiro para real.

Page 54: Aula04   ponteiros e conversao

Conversão implícita

char

int

float

double

Page 55: Aula04   ponteiros e conversao

Conversão implícita

● O compilador gcc não acusa erro se for esquecida a conversão de um tipo mais abrangente para um tipo menos abrangente. Mas você será avisado caso esteja fazendo.

● Exemplo:

float f = 1.2;int i = f;

Page 56: Aula04   ponteiros e conversao

Conversão explícita

● A conversão explícita ocorre quando se deseja forçar a conversão entre tipos.

● Utiliza-se o nome do tipo a ser convertido entre parentêses.

● Exemplo:

float f = 1.2;int i = (int) f;

Page 57: Aula04   ponteiros e conversao

Conversão explícita

● É útil quando se sabe que tipo de dado está armazenado em uma certa variável, evitando os avisos dos compiladores.

● Deve ser usado com extrema sabedoria, pois dados podem ser perdidos!– 0.0000122323 ≠ 0.

● Para se utilizar o ponteiro sem tipo, deve ser utilizada esta conversão.– Exemplo:

char c = 'a';void* p = (void*) &c;

Page 58: Aula04   ponteiros e conversao

Incremento e decremento

● Ao se utilizar adição e subtração com ponteiros o comportamento destas operações serão diferentes do apresentado anteriormente.

● A soma e a subtração são realizadas em unidades que correspondem ao tamanho em bytes do tipo de dado que aquele ponteiro faz referência.

Page 59: Aula04   ponteiros e conversao

Incremento e decremento

● Exemplo 1:

Page 60: Aula04   ponteiros e conversao

Incremento e decremento

● No Exemplo 1, o valor do ponteiro pchar é aumentado de 1 como é feito normalmente com o ++.

● Veja que o valor de pchar foi aumentado de apenas mais uma unidade.

Page 61: Aula04   ponteiros e conversao

Incremento e decremento

● Exemplo 2:

Page 62: Aula04   ponteiros e conversao

Incremento e decremento

● Exemplo 3:

Page 63: Aula04   ponteiros e conversao

Exercícios

1) Escreva um programa com sizeof e verifique o tamanho dos seguintes tipos de dados: unsigned int *, int *, long*, float*, void*. Responda: qual o tamanho de cada um?

Page 64: Aula04   ponteiros e conversao

Exercícios

2) Por que o tamanho dos ponteiros da questão 1 são iguais apesar de serem ponteiros para tipos diferentes?

Page 65: Aula04   ponteiros e conversao

Exercícios

● Lista!