Ponteiros e vetores
Nas aulas práticas, já discutimos parcialmente a relação entre vetores (ou matrizes) e ponteiros. Observe o seguinte comando em C, que solicitará quatro espaços contíguos de memória, capazes de armazenar quatro valores do tipo inteiro.
int vet[] = {1,2,3,4};
Quando começou a trabalhar com vetores em AED1, você provavelmente tentou executar o seguinte comando:
printf("%d", vet);
A resposta, como já sabemos, não era uma impressão bonita do vetor declarado anteriormente.
A seguir, vamos entender como funciona a alocação de memória para estruturas de dados homogêneas (vetores e matrizes) e o porquê de a impressão direta do vetor em C não funcionar como desejamos.
📚 Alocação de vetores
Uma característica importante com relação ao uso de vetores em C consiste no fato de que, ao declararmos um vetor, precisamos declarar também quantos elementos ele armazenará. Isso é fruto da necessidade de alocação de memória (afinal, precisa-se garantir n
espaços contíguos de memória para armazenar os elementos daquele vetor), mas também nos oferece uma vantagem.
Vamos acompanhar o comando a seguir:
int vet[4] = {1,2,3,4};
Por regras especiais da linguagem de programação C, a variável que representa um vetor será um ponteiro, que contém o endereço de memória da primeira posição do vetor. Logo, a variável vet
contém o endereço de memória que armazena o valor 1
, equivalente à vet[0]
.
Vejamos:
#include <stdio.h>
int main()
{
int vet[] = {1,2,3,4};
printf("vet[0] => %p\n", &vet[0]);
printf("vet => %p\n", vet);
return 0;
}
#include <stdio.h>
int main()
{
int vet[] = {1,2,3,4};
printf("vet[0] => %p\n", &vet[0]);
printf("vet => %p\n", vet);
printf("&vet => %p\n", &vet);
return 0;
}
Acessando elementos com ponteiros
Se vet
é um ponteiro que aponta para a primeira posição do vetor, essa variável também está suscetível à aritmética de ponteiros. Observe o comando a seguir, que visa a imprimir o valor das duas primeiras posições do vetor:
#include <stdio.h>
int main()
{
int vet[] = {1,2,3,4};
printf("vet[0] => %d\n", *vet); // imprime a primeira posição
printf("vet[1] => %d\n", *(vet+1)); // imprime a segunda posição
return 0;
}
Passando vetores para funções
Embora a abordagem a seguir não seja necessária, já que vetores são naturalmente passados por referência, podemos passar um vetor como parâmetro a uma função que recebe ponteiro:
#include <stdio.h>
void receberVetor(int *euSouUmPonteiro){ // recebendo um ponteiro
printf("Primeiro elemento: %d\n", *euSouUmPonteiro);
printf("Segundo elemento: %d\n", *(euSouUmPonteiro+1));
/* ou, alternativamente, da forma tradicional: */
printf("Terceiro elemento: %d\n", euSouUmPonteiro[2]);
printf("Quarto elemento: %d\n", euSouUmPonteiro[3]);
}
int main()
{
int vet[] = {90,27,14,31};
receberVetor(vet); // passando o vetor, como antes
return 0;
}
Vamos provar que o oposto também é verdade:
#include <stdio.h>
void receberVetor(int euSouUmVetor[]){
printf("Primeiro elemento: %d\n", *euSouUmVetor); // acessando como ponteiro
printf("Segundo elemento: %d\n", *(euSouUmVetor+1));
}
int main()
{
int vet[] = {90,27,14,31};
receberVetor(vet); // passando o vetor, como antes
return 0;
}