Alocação dinâmica de matrizes

Para entendermos a alocação dinâmica de matrizes, precisamos relembrar que matrizes são armazenadas como vetores de vetores. Para não ser redundante, é importante lembrar que os princípios aplicáveis aos vetores (como a realocação em tempo de execução) são aplicáveis também às matrizes.

Há, entretanto, algumas particularidades. Antes de prosseguirmos, vamos relembrar a declaração tradicional de matriz, que tem o seguinte padrão:

int matriz[qtdeLinhas][qtdeColunas];

Na alocação dinâmica de matriz, temos dois caminhos distintos.

1️⃣ Caso 1: Matriz como vetor

A primeira possibilidade para se trabalhar com matrizes de forma dinâmica envolve declará-la como um grande vetor:

int *matriz = (int*)calloc(qtdeLinhas*qtdeColunas, sizeof(int));

Em uma matriz 2x2, poderíamos acessar suas posições da seguinte forma:

#include <stdio.h>
#include<stdlib.h>

int main()
{
    int qtdeLinhas = 2;
    int qtdeColunas = 2;
    int *matriz = (int*)calloc(qtdeLinhas*qtdeColunas, sizeof(int));
    
    matriz[0] = 7;
    matriz[1] = 14;
    matriz[2] = 21;
    matriz[3] = 28;

    return 0;
}

Todavia, toda a representação de matriz deixaria de fazer sentido. Para contornar essa situação, temos algumas estratégias.

Percorrendo a matriz

Para percorrer uma matriz usando colchetes, temos a seguinte possibilidade:

matriz[linhaDesejada * qtdeColunas + colunaDesejada];

Vamos lá:

#include <stdio.h>
#include<stdlib.h>

int main()
{
    int qtdeLinhas = 2;
    int qtdeColunas = 2;
    int *matriz = (int*)calloc(qtdeLinhas*qtdeColunas, sizeof(int));

    /* Para preencher */
    for(int i = 0; i < qtdeLinhas; i++){
        for(int j = 0; j < qtdeColunas; j++){
            matriz[i * qtdeColunas + j] = rand() % 10;
        }
    }

    /* Para imprimir */
    for(int i = 0; i < qtdeLinhas; i++){
        for(int j = 0; j < qtdeColunas; j++){
            printf("%d ", matriz[i * qtdeColunas + j]);
        }
        printf("\n");
    }

    return 0;
}

2️⃣ Caso 2: Matriz como um vetor de vetores

A segunda estratégia pode ser um pouco mais familiar. Ela envolve considerar a matriz como um ponteiro duplo, tornando a sua representação muito próxima daquilo que vimos quando estudamos aritmética de ponteiros em matrizes:

int **matriz = (int**)calloc(nroDeLinhas, sizeof(int*));

Depois, precisamos criar os vetores que representam as colunas, com a seguinte operação:

matriz[numeroDaLinha] = (int*)calloc(qtdeColunas, sizeof(int));

Agora, vamos ao código completo:

#include <stdio.h>
#include<stdlib.h>

int main()
{
    int qtdeLinhas = 2;
    int qtdeColunas = 2;
    
    int **matriz = (int**)calloc(qtdeLinhas, sizeof(int*));
    
    /* Criar colunas */
    for(int i = 0; i<qtdeLinhas; i++){
        matriz[i] = (int*)calloc(qtdeColunas, sizeof(int));
    }
    
    /* Percorrer com aritmética */
    for(int i = 0; i<qtdeLinhas; i++){
        for(int j = 0; j<qtdeColunas; j++){
           *(*(matriz+i)+j) = rand() % 10;
        }
    }
    
    /* Imprimir com colchete */
    for(int i = 0; i<qtdeLinhas; i++){
        for(int j = 0; j<qtdeColunas; j++){
            printf("%d ", matriz[i][j]);
        }
        printf("\n");
    }

    /* Liberar a memória */
    for(int i = 0; i < qtdeLinhas; i++) {
        free(matriz[i]);
    }
    free(matriz);

    return 0;
}

📦 Mudando o tamanho da matriz

Assim como com vetores, podemos realocar o tamanho da matriz, aumentando sua quantidade de linhas e colunas.

Adicionando linhas

Para realocar a quantidade de linhas da matriz, podemos usar o seguinte código:

    int totalLinhas = 4; // qtdeLinhas + novas
    matriz = (int**)realloc(matriz, totalLinhas * sizeof(int*));

    // Alocar e inicializar as novas linhas
    for(int i = qtdeLinhas; i < totalLinhas; i++) {
        matriz[i] = (int*)calloc(qtdeColunas, sizeof(int));
        for(int j = 0; j < qtdeColunas; j++) {
            matriz[i][j] = 0;
        }
    }
    qtdeLinhas = totalLinhas;

Adicionando colunas

Para realocar a quantidade de colunas da matriz, podemos usar o seguinte código:

    int totalColunas = 4; // qtdeColunas + novas
    for(int i = 0; i < qtdeLinhas; i++) {
        matriz[i] = (int*)realloc(matriz[i], totalColunas * sizeof(int)); 
        for(int j = qtdeColunas; j < totalColunas; j++) {
            matriz[i][j] = 0;
        }
    }
    qtdeColunas = totalColunas;

📖 Bibliografia

Livros

  • Backes, A. (2018). Linguagem C - Completa e Descomplicada.