Vetores como ponteiros no CNeste e nos próximos tutoriais, veremos que os ponteiros e os vetores têm uma ligação muito forte.

[clearboth]
[toggle title=”Vetores como ponteiros”]

Vamos dar agora uma idéia de como o C trata vetores. Quando você declara uma matriz da seguinte forma:

tipo_da_variável nome_da_variável [tam1][tam2][tamN];

O compilador C calcula o tamanho, em bytes, necessário para armazenar esta matriz. Este tamanho é:

tam1 x (vezes) tam2 x(vezes) tam3 x … x(vezes)  tamN x(vezes)  tamanho_do_tipo

O compilador irá alocar este número de bytes num espaço livre de memória. O nome da variável que você declarou é na verdade um ponteiro para o tipo da variável da matriz. Este conceito é fundamental, porque, tendo alocado na memória o espaço para a matriz, ele toma o nome da variável (que é um ponteiro) e aponta para o primeiro elemento da matriz. Mas aí surge a pergunta: então como é que podemos utilizar a seguinte notação?

nome_da_variável[índice]

Isto pode ser facilmente explicado desde que entenda que a notação acima é absolutamente equivalente a se fazer:

*(nome_da_variável+índice)

Agora podemos entender como é que funciona um vetor! Vamos ver o que podemos tirar de informação deste fato. Fica claro que, por exemplo, porque é que, no C, a indexação começa com zero. É porque, ao pegarmos o valor do primeiro elemento de um vetor, queremos, de fato, *nome_da_variável e então devemos ter um índice igual a zero. Então sabemos que:

*nome_da_variável

É equivalente a:

nome_da_variável[0]

Apesar de, na maioria dos casos, não fazer muito sentido, poderíamos ter índices negativos. Estaríamos a utilizar posições de memória antes do vetor. Isto explica também porque o C não verifica a validade dos índices. Ele não sabe o tamanho do vetor. Ele apenas aloca a memória, ajusta o ponteiro do nome do vetor para o início do mesmo e, quando você utiliza os índices, encontra os elementos requisitados. Vamos ver agora um dos usos mais importantes dos ponteiros: a varredura sequencial de uma matriz. Quando temos que varrer todos os elementos de uma matriz de uma forma sequencial, podemos utilizar um ponteiro, o qual vamos incrementando. Qual a vantagem? Considere o seguinte programa para zerar uma matriz:

main ()
{
float matrx [50][50];
int i,j;
for (i=0;i<50;i++){
for (j=0;j<50;j++){
matrx[i][j]=0.0;
}
}
}

Podemos reescrevê- lo de uma forma muito mais eficiente:

main ()
{
float matrx [50][50];
float *p;
int count;
p=matrx[0];
for (count=0;count<2500;count++){
*p=0.0;
p++;
}
}

Você consegue ver porque é que o segundo programa é mais eficiente? Simplesmente porque cada vez que se faz matrx[i][j] o programa tem que calcular o deslocamento para dar ao ponteiro. Ou seja, o programa tem que calcular 2500 deslocamentos. No segundo programa o único cálculo que deve ser feito é o de um incremento de ponteiro. Fazer 2500 incrementos num ponteiro é muito mais rápido que calcular 2500 deslocamentos completos. Há uma diferença entre o nome de um vetor e um ponteiro que deve ser destacada: um ponteiro é uma variável, mas o nome de um vetor não é uma variável. Isto significa, que não se consegue alterar o endereço que é apontado pelo “nome do vetor”, ou seja:

int vetor[10];
int *ponteiro, i;
ponteiro = &i;
/* as operacoes a seguir sao invalidas */
vetor = vetor + 2; /* ERRADO: vetor nao e' variavel */
vetor++; /* ERRADO: vetor nao e' variavel */
vetor = ponteiro; /* ERRADO: vetor nao e' variavel */

Teste as operações acima no seu compilador. Ele dará uma mensagem de erro. Alguns compiladores dirão que vetor não é um Lvalue. Lvalue, significa “Left value”, um símbolo que pode ser colocado do lado esquerdo de uma expressão de atribuição, isto é, uma variável. Outros compiladores dirão que tem-se “incompatible types in assignment”, tipos incompatíveis numa atribuição.

/* as operacoes abaixo sao validas */
ponteiro = vetor; /* CERTO: ponteiro e' variavel */
ponteiro = vetor+2; /* CERTO: ponteiro e' variavel */

[/toggle]
[toggle title=”Nota importante”]

Nota: O que aprendeu neste tutorial é de extrema importância. Não avance para o próximo tutorial antes de entender o conteúdo acima.

[/toggle]

Gostou do tutorial? Então deixe um comentário abaixo!

Anúncios