IAED, 2012/2013 Ponteiros e Tabelas K&R: Capitulo 5 IAED, 2012/2013 2 Ponteiros e Tabelas • Ponteiros e endereços • Ponteiros e argumentos de funções • Ponteiros e tabelas • Alocação dinâmica de memória • Aritmética de ponteiros • Tabelas de ponteiros e ponteiros para ponteiros • Tabelas multi-dimensionais • Inicialização de tabelas de ponteiros • Argumentos da linha de comandos • Ponteiros para funções
27
Embed
Ponteiros e Tabelas - Técnico Lisboa · • Tabelas de ponteiros e ponteiros para ponteiros ... 3 5 IAED, 2012/2013 Ponteiros e Endereços • Um ponteiro é uma variável que contém
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
1
IAED, 2012/2013
Ponteiros e Tabelas
K&R: Capitulo 5
IAED, 2012/2013 2
Ponteiros e Tabelas
• Ponteiros e endereços • Ponteiros e argumentos de funções • Ponteiros e tabelas • Alocação dinâmica de memória • Aritmética de ponteiros • Tabelas de ponteiros e ponteiros para ponteiros • Tabelas multi-dimensionais • Inicialização de tabelas de ponteiros • Argumentos da linha de comandos • Ponteiros para funções
2
IAED, 2012/2013 3
Ponteiros em C
=
IAED, 2012/2013 4
Ponteiros e Endereços
• Na memória do computador cada posição é referenciada por um endereço, atribuído de forma sequencial
• Posições adjacentes têm endereços consecutivos
3245434
3245435
3245436
3245437
3
IAED, 2012/2013 5
Ponteiros e Endereços
• Um ponteiro é uma variável que contém o endereço de outra variável
3245434
3245435
3245436
3245437
3245438
3245439
3245440
3245441
3245442
3245443
‘a’
3245435 char c = ‘a’; char *ptr = &c;
aponta
declaração de um ponteiro inicializo ptr com
o endereço de c
IAED, 2012/2013 6
Um ponteiro em C
é um endereço de memória
IAED, 2012/2013 6
4
IAED, 2012/2013 7
Um ponteiro em C
é um endereço de memória
IAED, 2012/2013 7
IAED, 2012/2013 8
Ponteiros e Endereços
• Declaração de um ponteiro para tipo <tipo>
• Exemplos
<tipo> *<variável>;
char *cptr; /* ponteiro para caracter */
int *iptr; /* ponteiro para inteiro */
double *dptr; /* ponteiro para double */
5
IAED, 2012/2013 9
Ponteiros e Endereços
• Operador & aplicado a x representa o endereço de x
#include <stdio.h>
int main() {
int y, x = 1;
int *px;
px = &x; y = *px;
*px = 0;
printf("%d %d\n", x, y);
return 0;
}
IAED, 2012/2013 10
Ponteiros e Endereços
• Operador * aplicado a px representa o conteúdo da posição de memória apontada por px
#include <stdio.h>
int main() {
int y, x = 1;
int *px;
px = &x;
y = *px; *px = 0; printf("%d %d\n", x, y);
return 0;
}
6
IAED, 2012/2013
Utilizações do * (asterisco)
• Declaração do ponteiro
– x é um ponteiro para um inteiro
• Conteúdo da posição de memória apontada pelo ponteiro
– o valor 4 é atribuído ao conteúdo da posição de memória apontada por x
11
int *x;
*x = 4;
IAED, 2012/2013 12
Utilização de Ponteiros
• O valor de retorno de uma função pode ser um ponteiro
• O argumento de uma função pode ser um ponteiro
• Prioridade de & e * é superior à dos operadores aritméticos – y = *px + 1 funciona como esperado – ++*px incrementa o valor de x – (*px)++ (os parênteses são necessários)
int *xpto();
int abcd(char *a, int *b);
7
IAED, 2012/2013 13
Passagem de Parâmetros para Funções
• Em C os parâmetros são passados por valor
• Não funciona como necessário !
void swap(int a, int b) { int aux;
aux = a;
a = b;
b = aux; }
IAED, 2012/2013 14
Passagem de Parâmetros para Funções
• Passagem por referência consegue-se enviando ponteiros
• Chamada deverá ser swap(&x, &y)
void swap(int *a, int *b) { int aux;
aux = *a;
*a = *b;
*b = aux; }
8
IAED, 2012/2013 15
Ponteiros e Tabelas
• Em C existe uma relação entre ponteiros e tabelas
• a é um ponteiro para a primeira posição da tabela
#include <stdio.h>
int main() {
int a[6] = {1, 2, 3, 4, 5, 6 };
int *pa = a;
printf("%d %d %d\n", a[2], *(a+2), *(pa+2));
return 0; }
IAED, 2012/2013 16
Ponteiros e Tabelas
• A declaração int *p1; declara o mesmo que int p2[]; – p1 pode ser alterado – p2 não pode ser alterado – int p2[]; só pode ser utilizado em certos casos
• A declaração int p3[100]; declara uma tabela com 100 inteiros e aloca memória na quantidade necessária – p3 não pode ser alterado
• A declaração char *text; não aloca qualquer memória – no entanto char *text = "ola"; aloca;
9
IAED, 2012/2013 17
Ponteiros e Tabelas
• Qual a diferença entre as duas declarações seguintes ?
• Ambas alocam 4 bytes e copiam para essa posição de memória a sequência de caracteres 'o','l','a','\0'
• Em ambos os casos é possível modificar o conteúdo da memória alocada
• Não é possível alterar o valor de t1, ou seja não é possível pôr t1 a apontar para outra posição de memória
• É possível alterar o valor de t2
char t1[] = "ola"; char *t2 = "ola";
IAED, 2012/2013 18
Ponteiros e Tabelas
• Exemplo: cópia de strings void strcpy(char *s, char *t)
• Definido em stdlib.h – Necessário #include <stdlib.h>
• Utilizado para indicar situações especiais
• Na realidade NULL == 0
int *ptr = NULL;
11
IAED, 2012/2013 21
Alocação Dinâmica de Memória
• Alocação estática
– Memória alocada durante o scope da variável – Não é possível libertar quando não necessária – Não é possivel utilizar fora do scope
• Solução: alocação dinâmica !
int tab[100];
IAED, 2012/2013 22
Alocação Dinâmica de Memória
• Função malloc
• Recebe como argumento o número de bytes – Tipo size_t representa uma dimensão em bytes
• Devolve um ponteiro (endereço) para o primeiro byte do bloco de memória contígua alocada (mas não inicializada) – void * indica um ponteiro para um tipo não especificado – permite utilização com qualquer tipo de dados – posteriormente faz-se conversão para o tipo correcto por type cast
void *malloc(size_t size);
int *tab; tab = (int *) malloc(4*100);
12
IAED, 2012/2013 23
Alocação Dinâmica de Memória
• Função malloc
• Recebe como argumento o número de bytes – Tipo size_t representa uma dimensão em bytes
• Devolve um ponteiro (endereço) para o primeiro byte do bloco de memória contígua alocada (mas não inicializada) – void * indica um ponteiro para um tipo não especificado – permite utilização com qualquer tipo de dados – posteriormente faz-se conversão para o tipo correcto por type cast
void *malloc(size_t size);
int *tab; tab = (int *) malloc(sizeof(int)*100);
IAED, 2012/2013 24
Alocação Dinâmica de Memória
• malloc retorna NULL caso não seja possível alocar a memória pedida
• Verificar sempre o resultado do pedido de memória
int *pvector
pvector = (int *) malloc(sizeof(int)* VEC_SIZE);
if (pvector == NULL){
fprintf(stderr, “Erro: falta de memória\n”);
exit(-1); }
13
IAED, 2012/2013 25
Alocação Dinâmica de Memória
• Memória válida desde o ponto em que é alocada até ser libertada ou até o programa terminar
• Exemplo: alocar memória para uma string e copiá-la
char *strsav(char *s)
{ char *d;
d = (char *) malloc(sizeof(char)*(strlen(s)+1));
strcpy(d, s);
return d; }
IAED, 2012/2013 26
Alocação Dinâmica de Memória
• Libertação de memória é efectuada com a função free
• Recebe como argumento o ponteiro para a primeira posição do bloco de memória contígua a libertar
• Não devolve nada
• Tanto malloc como free estão definidas em stdlib.h – Necessário #include <stdlib.h>
void free(void *ptr);
14
IAED, 2012/2013 27
Alocação Dinâmica de Memória
• Função realloc
• Recebe ponteiro ptr para bloco de memória antigo e dimensão size do novo bloco de memória
• Devolve ponteiro para novo bloco de memória • Copia valores do bloco antigo para o novo
– Se novo fôr mais pequeno, só copia até caber – Se novo fôr maior, copia tudo e deixa o resto sem ser inicializado
void *realloc(void *ptr, size_t size);
IAED, 2012/2013 28
Alocação Dinâmica de Memória
• Função calloc
• Aloca memória para uma tabela de nmemb elementos, cada um com dimensão size em bytes
• Devolve ponteiro para a tabela alocada • A mesma coisa que malloc(nmemb*size); • A memória alocada é inicializada toda a 0 (zeros)
void *calloc(size_t nmemb, size_t size);
15
IAED, 2012/2013 29
Aritmética de Endereços
• É possível efectuar + e - com ponteiros
int x = 10; int *px = &x;
x px
IAED, 2012/2013 30
Aritmética de Endereços
• É possível efectuar + e - com ponteiros
• Incrementa/decrementa na dimensão do tipo para o qual aponta – sizeof(int) neste caso
int x = 10; int *px = &x;
px++; x px
16
IAED, 2012/2013 31
Tabelas de Ponteiros
• É possível definir tabelas em que cada elemento é um ponteiro
• Neste caso definimos uma tabela com 100 elementos, em que cada elemento é um ponteiro para int
• tabptr também é um ponteiro
int *tabptr[100];
IAED, 2012/2013 32
Tabelas Multi-Dimensionais
• A declaração int x[NROWS][NCOLS] declara uma matriz – Aloca espaço NROWS*NCOLS de inteiros
• É equivalente a int *x[NROWS] – Aloca espaço NROWS de ponteiros para inteiros – Permite que linhas tenham tamanhos diferentes
• Elemento na linha i e coluna j é x[i][j]
• Na prática, ponteiros para tabelas são mais usados • Qualquer número de dimensões pode ser usado • Primeira dimensão pode não ser especificada