Escolar Documentos
Profissional Documentos
Cultura Documentos
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);
} 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
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; }