Endereçamento de Memória
Programação13205: Engenharia Informática13901: Matemática e Aplicações
Cap. 8— Endereçamento de Memória
Endereçamento de Memória
Sumário:
• O que nós já sabemos sobre endereçadores (ou apontadores ou ponteiros)
• Declaração de variáveis endereçadoras
• Inicialização de variáveis endereçadoras
• Acesso ao valor e ao endereço duma variável
• Apontadores e arrays
• Aritmética de endereçadores
• Acesso aos elementos dum array através de endereços
• Passagem de arrays para funções
Endereçamento de Memória
Valor de uma variávelEndereço de uma variável
#include <stdio.h>int main(){
int j = 1;printf("O valor de j = %d\n",j);printf("O endereco de j = %p\n",&j);return 0;
}
1 248623
memória
j
valor de jendereço de j
Saída no ecrã:O valor de j = 1O endereco de j = 248623
REVISÃO
Endereçamento de Memória
Acesso ao valor de uma variável
• Há duas formas de ler (aceder a) o valor duma variável em memória:
– Leitura directa (ou acesso directo). Utiliza-se o nome da variável.
– Leitura indirecta (ou acesso indirecto). Utiliza-se operador de valoração * seguido de nome de variável apontadora.
– Exemplo:
• O acesso ao valor 1.2 de j faz-se através do uso:
– da variável j– da variável p que aponta (ou endereça) para j
1.2
1342167
1342167
memória
j
valor de jendereço de j
p
REVISÃO
Endereçamento de Memória
O que é que nós já sabemos sobre variáveis endereçadoras?
1342167
memória
j
valor de jendereço de j
p
• Tal como qualquer variável, uma variável endereçadora tem:
– nome
– valor
– endereço
• Mas, o seu valor é um endereço de memória. 1342170
Endereçamento de Memória
Declaração de variáveis endereçadoras
• Diagrama de sintaxe
em que
nome: é o identificador da variável apontadora
tipo : é o tipo do dado que será endereçado
* : indicador de que a variável declarada é do tipo apontador.
• Exemplosint *x;
float *y;
nometipo * ;
Endereçamento de Memória
Inicialização de variáveis endereçadoras
• A inicialização de variáveis endereçadoras faz-se através do operador & (endereço de).
• Exemplofloat x = 5.0;
float *p;p = &x;
5.0
1342167
1342167x
p 1342173
ATENÇÃO:A constante simbólica NULL, quando atribuída a uma variável endereçadora, indica que esta não endereça nenhuma variável.
Endereçamento de Memória
Acesso ao valor e ao endereço de uma variável
• Há duas formas de ler (aceder a) o valor duma variável em memória:
– Leitura directa (ou acesso directo). Utiliza-se o nome da variável.
– Leitura indirecta (ou acesso indirecto). Utiliza-se operador de valoração * seguido de nome de variável apontadora.
- O acesso ao endereço duma variável é feito através do operador &.
• Exemploint a = 5, b=10;int *p;
p = &a;
510
13456
13458b
p
a 13456
13461
Acesso a:a ® 5&a ® 13456b ® 10&b ® 13458p ® 13456&p ® 13461*p ® 5
Endereçamento de Memória
Endereçadores e arrays
• Uma das principais aplicações de apontadores é na manipulação de arrays e strings (cadeias de caracteres).
• Normalmente a utilização do nome duma variável dá acesso ao seu valor.
• EXCEPÇÃO: no caso dum vector, a utilização do seu nome dá acesso ao seu endereço que é o endereço do seu primeiro elemento.
• Exemplo
int v[3] = {5,10,20};int *p, *q;p=v; q=&v[0];
p
v[0] 13456
13462
q 13465
1345813460
v
v[1]v[2]
13456
51020
13456
13456
Endereçamento de Memória
Aritmética de endereçadores
• Dado que os endereçadores armazenam números (endereços) que representam posições de memória, podem ser sobre eles realizadas algumas operações aritméticas:
• Incrementação
– Um endereçador pode ser incrementado como qualquer variável.
– A incrementação de 1 unidade não significa que o endereço armazenado no endereçador é incrementado de 1 byte.
– O que acontece é que um endereçador para um dado tipo avança sempre sizeof(tipo)bytes por cada unidade de incremento.
• Decrementação
– Faz exactamente o contrário da incrementação.
– Um endereçador para um dado tipo retrocede sizeof(tipo) bytes por cada unidade de decremento.
Endereçamento de Memória
Exemplo:
#include <stdio.h>int main(){
int x=5;int *p=&x;
printf(“%d %p\n",x,p);printf(“%d %p\n",x+1,p+1);
return 0;}
Saída no ecrã:5 2345686 234570
Endereçamento de Memória
Aritmética de endereçadores (cont.)
• Diferença
– O resultado da diferença entre dois endereçadores é o número de elementos que existem entre os dois endereços.
– RESTRIÇÃO: Os dois endereçadores têm de ser do mesmo tipo.
• Comparação
– É possível comparar endereçadores através dos operadores relacionais (>, <, >=, <=, ==, !=).
– RESTRIÇÃO: Os dois endereçadores têm de ser do mesmo tipo.
Endereçamento de Memória
Exemplo:
#include <stdio.h>int main(){
int v[5]={5,10,15,20,25};int *p=v;
int *q=&v[4];printf(“%p\n",q-p);
return 0;}
Saída no ecrã:4
Endereçamento de Memória
Acesso aos elementos dum array através de endereçamento
• Exemplo
int v[5] = {5,10,15,20,25};int *p=v; // é o mesmo que p=&v[0]
Exemplificando o acesso ao elemento 15:
v[2] | Inteiro existente na posição índice 2.
*(p+2) | Como p contém o endereço do 1º elemento, se lhe adicionarmos 2
| obtemos o endereço do 3º elemento. O 3º elemento é então obtido através d operador *.
*(v+2) | Mesma estratégia que a anterior pois p=v=&v[0].
p[2] | O endereçamento através de parêntesis rectos pode ser feito também por apontadores,
| como se de um vector se tratasse.
Endereçamento de Memória
Passagem de arrays para funções
• Sempre que na chamada duma função se passa um array como parâmetro, a função não recebe o array na totalidade, mas somente o endereço do 1º elemento, pois estamos a passar v=&v[0].
• Se se passa um endereço para a função, a variável que o recebe terá de ser um apontador para o tipo dos elementos do array.
• É por esta razão que no cabeçalho duma função, que recebe um array como argumento, aparece normalmente um apontador a receber o respectivo parâmetro.
Endereçamento de Memória
Exemplo#include <stdio.h>int soma( int*, int);
int main(void){int v[5] = {5,34,56,1,6};float media;
media = soma(v,5) / 5.0;
printf(“media= %f\n”, media);return 0;
}
int soma( int *a, int N){
int i, sum=0;
for ( i=0; i<N; i++)sum = sum + a[i];
return sum;}
NOTA:
O argumento a da função soma é um endereçador para um inteiro que receberá o endereço do array vaquando da chamada da referida função.
102
main somaN
sum
&v[0]a
5
media
5 34 56
i ® 0 1 2 3 4
1 6v
FIM