Como utilizar ponteiros com matrizes

Matrizes e ponteiros estão intimamente ligados em C. Para usar matrizes efetivamente, você precisa saber como usar os ponteiros com elas. O total entendimento da relação entre os dois provavelmente vai requerer dias de estudo e experiências, porém esse esforço será recompensado.

Vamos começar com um exemplo simples de matrizes em C:

#define MAX 10

void main()
{
    int a[MAX];
    int i;
    int *p;

    p=a;
    for(i=0; i<MAX; i++)
        a[i]=i;
    printf("%d ",*p);
}

Digite este código e tente compilá-lo. Você verá que a linguagem C não compilará. Para copiar a em b, você precisa digitar algo como:  

Ou, trocando em miúdos:     

Melhor ainda, use o utilitário memcpy em string.h.  

As matrizes em C são incomuns, enquanto as variáveis a e b não são, tecnicamente, matrizes.  Em vez disso, elas são ponteiros permanentes para matrizes. a e b apontam permanentemente para os primeiros elementos de suas respectivas matrizes (elas mantêm os endereços de a[0] e b[0], respectivamente). Visto que são ponteiros permanentes, você não pode alterar seus endereços.  Logo, a instrução a=b; não funciona.  

Sendo a e b ponteiros, você pode fazer várias coisas interessantes com ponteiros e matrizes. Por exemplo, o código seguinte funciona:    

A instrução p=a; funciona pois a é um ponteiro. Tecnicamente, a aponta para o endereço do elemento zero da matriz. Como este elemento é um inteiro, a é um ponteiro de inteiro simples.  Assim sendo, declarar p como um ponteiro de um inteiro e defini-lo como igual a a funciona.  Outro modo de dizer a mesma coisa seria substituir p=a; por p=&a[0];. Considerando que a contém o endereço de a[0], a e &a[0] significam a mesma coisa.  

A figura abaixo mostra o estado das variáveis antes de iniciar a execução do loop for:   

Agora que p está apontando para o elemento 0 de a, você pode fazer algumas coisas incomuns com ele.  A variável a é um ponteiro permanente e não pode ser alterada, mas p não está sujeita a tais restrições.  Na verdade, a linguagem C o estimula a mudá-lo usando a aritmética de ponteiro. Por exemplo, se você disser p++;, o compilador sabe que p aponta para um inteiro e esta instrução aumenta p o número apropriado de bytes para transferi-lo para o próximo elemento na matriz. Se p apontasse para uma matriz de estruturas de 100 bytes, p++; mudaria p para mais de 100 bytes. A linguagem C se encarrega dos detalhes de tamanho de elemento.   

Você também pode copiar a matriz a em b usando ponteiros.  O seguinte código pode substituir (para i=0; i<MAX; a[i]=b[i], i++);:    

Você pode abreviar este código da seguinte maneira:     

Você pode abreviar ainda mais:   

E se você for além do final da matriz a ou b com os ponteiros p ou q?  Para a linguagem C isso não importa, pois ela continua aumentando p e q, copiando sobre outras variáveis. Você precisa ter cuidado ao indexar em matrizes em C, porque a linguagem C assume que você sabe o que está fazendo.   

Você pode passar uma matriz como a ou b para uma função de dois modos diferentes.  Imagine uma função dump que aceita uma matriz de inteiros como um parâmetro e imprime o conteúdo da matriz para stdout.  Há duas maneiras de codificar dump:  

ou:      

A variável nia (number_in_array) é necessária para que o tamanho da matriz seja conhecido.  Note que apenas um ponteiro para a matriz, em vez do conteúdo da matriz, passa para a função. Observe também que as funções em C podem aceitar matrizes de tamanho variável como parâmetros.