Você está na página 1de 4

Mtodos Computacionais em F e sica 2004/2 - IF/UFRJ 13/09/04

Ponteiros e vetores
Monica Bahiana

Manipulao de Endereos ca c
Um ponteiro uma varivel que guarda um endereo, capaz de localizar uma porao de memria. Como e a c c o outras variveis, pode ser dos tipos double, float, int e char, alm de poder ser void, ou seja no ter tipo a e a denido, e ser do tipo de uma estrutura, como os do tipo FILE que usamos para na manipulaao de arquivos. c J vimos endreos, no uso da funos scanf, sem dvida o uso de ponteiros nos argumentos de funoes a c ca u c e uma das aplicaoes mais freqentes deste tipo de varivel. Veremos aqui tambm seu uso na deniao de c u a e c arrays. O operador unrio & d o endereo de uma varivel. Assim, quando usamos scanf("%f",&k) para ler a a c a o valor de k, informamos ` funao o endereo da varivel k, ou seja, a que posio da memria ela est a c c a ca o a associada, e no o seu valor. O operador unrio * o operador indireo ou derreferncia, ele acessa o a a e ca e objeto para o qual o ponteiro aponta. Veja como funciona: int main(void) { float x, y; /* x e y sao variaveis reais */ float *p1, *p2; /* p1 e p2 sao ponteiros para variaveis reais, *p1 e *p2 sao reais */ x = 2.5; y = 0.8; p1 = &x; /* p1 aponta para x */ y = *p1; /* y agora vale 2.5 */ *p1 = 1.0; /* x agora vale 1.0 */ *p1 = *p1 + 5.0; /* x agora vale 6.0 */ p2 = p1; /* p2 tambem aponta para x */ return 0; } Uma nota de cautela importante neste momento. No exemplo acima mostramos que poss mudar o e e vel valor de uma varivel sem acess-la diretamente, pela manipulao de um ponteiro que aponte para o seu a a ca endereo. Por isso todo o cuidado pouco ao alinhar os ponteiros, devemos sempre ter em mente o que est c e a sendo apontado por um ponteiro em uma dada linha do cdigo. o Tambm, devemos ter cuidado com a inicializaao dos ponteiros: todo ponteiro deve ser inicializado. e c O exemplo abaixo vai gerar uma mensagem de erro do tipo Segmentation fault ou Access violation: #include <stdio.h> int main(void) { float *x, y; y = 2; *x = 3; printf("%f return 0;

%f\n", y, *x);

Mtodos Computacionais em F e sica 2004/2 - IF/UFRJ 13/09/04

} No cdigo acima o ponteiro x est apontando para um endereo aleatrio, que provavelmente nem pertence o a c o ao executvel, quando fazemos *x=3 estamos tentando escrever nesse endereo, e seremos impedidos pelo a c sistema operacional. Para corrigir alinhamos o ponteiro x com algum endereo vlido: c a #include <stdio.h> int main(void) { float *x, y; y = 2; x = &y; *x = 3; printf("%f return 0; }

%f\n", y, *x);

Ponteiros e arrays
Um array uma seqncia consecutiva de blocos de memria, todos do mesmo tamanho. Por exemplo, float e ue o x[10] dene uma bloco de 10 objetos (cada um com o tamanho de um float), que so: x[0], x[1],. . . x[9]. a Por deniao, x o endereo do in c e c cio do bloco de memria completo, e x[i] armazena o contedo do o u endereo que ca no bloco de posiao i com relaao ao inicial, que o 0. c c c e Arrays e ponteiros so diretamente relacionados como veremos a seguir. Seja o array float a[10], que a consiste no conjunto de 10 blocos consecutivos de memria. Podemos denir um ponteiro que aponte para o qualquer elemento a[i]: float *pa, x, a[10]; int i; for(i = 0; i <= 9; i++){ a[i] = (i+1)*0.1; // a[0]=0.1 a[1]=0.2 ...a[9]=1.0 } pa = &a[2]; // p apontaara a[2] x = *pa; // x vale 0.3 x = *(pa+1) // x recebe o valor de a[3], x vale 0.4 pa = a; // pa aponta para a[0], equivalente a pa = &a[0] x = *(pa+2) // x recebe o valor de a[2], x vale 0.3 Vemos acima que, se pa aponta para um determinado elemento a[i] do array, ento pa+j aponta para o a elemento a[i+j], e esta uma forma muito ecaz de se caminhar sobre o array. Em resumo, temos as e seguinte expresses equivalentes: o pa = &a[0] e pa = a *(a+i) e a[i] a+i e &a[i] Pelos exemplos acima pode-se ter a idia errada de que ponteiros e arrays so a mesma coisa. Existe uma e a grande diferena entre um array e um ponteiro: um ponteiro uma varivel e nome de um array no. Assim, c e a a no exemplo abaixo, pa uma varivel, e o nome do array, a, um endereo, uma constante durante a e a e c execuao do programa. c pa = a e pa++ so expresses legais a o a = pa e a++ so ilegais. a

Mtodos Computacionais em F e sica 2004/2 - IF/UFRJ 13/09/04

Alocao dinmica de memria ca a o


Ao denirmos os arrays como tipo a[n], a quantidade de memria alocada (quer dizer, reservada) ca o denida no momento da compilaao. Durante a execuao podemos usar toda ou apenas uma parte da c c memria alocada. E muito mais conveniente ter o tamanho do array como um dos dados de entrada, ou o denido aps a execuao de parte do programa. Outras linguagens permitem apenas a deniao de arrays o c c maiores que qualquer tamanho poss no contexto, o que problemtico porque o programa acaba alocando vel e a muita memria que no usada, podendo tornar-se invivel. Se a estimativa for mal feita, e a quantidade o a e a de memria prevista for insuciente, ocorrer um erro de execuao pelo acesso a um endero de memria o a c c o no alocado pelo executvel. A linguagem C permite que memria seja alocada durante a execuao, por a a o c exemplo atravs da funaomalloc cujo prottipo void *malloc(size t size), denido em stdlib.h. O e c o e tipo size t um inteiro sem sinal retornado por sizeof. A funao malloc reserva memria para um objeto e c o de tamanho size, e retorna um ponteiro para o in dessa porao de memria. Por exemplo, se queremos cio c o alocar memria para n nmeros do tipo float, fazemos: o u float *v; v=(float *)malloc(n*sizeof(float)); Neste caso, v aponta para o primeiro bloco (do tamanho de um float) de memria alocado, seu contedo o u o valor de v[0], e v[i] contm o nmero oat da posiao i, com relaao a v. O valor de n pode ser e e u c c dado durante a execuo. Como alocamos n posioes o array est denido para i entre 0 e n-1. O acesso ca c a a endereos fora do espao alocado pode gerar problemas diversos, que dependem do sistema operacional c c utilizado. Um bom sistema operacional, como Linux, Windows NT, e verses de Windows posteriores ` 95, o a no permitem o acesso a regies de memria que no estejam sob o controle do executvel. Se isso ocorre, a a o o a a execuao interrompida e o compilador manda mensagens de erro como Segmentation fault, ou Access c e violation. Se o acesso permitido, o programa estar recebendo valores totalmente aleatrios, gerando e a o resultados errados. Enquanto a memria alocada por malloc no for liberada, ela continuar ` disposio do executvel at o a aa ca a e o m da execuao. Para liberar a memria para outros ns, existe a funao free, com prottipo void c o c o free(void *ptr), tambm em stdlib.h. Por exemplo, para liberar a memria alocada acima, fazemos e o float *v; v=(float *)malloc(n*sizeof(float)); free(v); As verses para arrays inteiros e de dupla preciso so anlogas, substituindo float pelo tipo desejado. o a a a Veja um exemplo de uso abaixo, no cdigo para um programa em que primeiro o nmero de linhas do o u arquivo contado, e s ento um vetor alocado. O arquivo dados.dat contm dados, cada valor em uma e o a e e linha. No sabemos de antemo quantos valores devem ser lidos, ento primeiro contamos o nmero de a a a u dados, simplesmente contando o nmero de caracteres linha nova u n. A funao fgetc(FILE *fp) l um caracter de cada vez, do arquivo associado a fp. Enquanto esse caracter c e no for igual a EOF, (End Of File, o caracter que indica que o arquivo chegou ao m), cada vez que ele igual a e ao caracter linha nova, o contador do nmero de linhas (N), incrementado. De posse do valor do nmero de e u dados, denimos o vetor x[N] por alocaao dinmica. c a #include <stdio.h> #include <stdlib.h> int main(void) { double *x; int N, i; char c; FILE *fp;

Mtodos Computacionais em F e sica 2004/2 - IF/UFRJ 13/09/04

fp = fopen("dados.dat", "r"); N = 0; while( (c=fgetc(fp)) != EOF){ if ( c == \n ) N++; } x = {(double *)malloc(N*sizeof(double)); rewind(fp); // volta para o inicio do arquivo for(i = 0; i <= N-1; i++){ fscanf(fp, "%lf",&x[i]); } . . . return 0; }

Você também pode gostar