Pergunta

Existe alguma maneira de criar uma matriz duplamente de tamanho variável em C (não C ++, apenas C)? Eu sei que para criar uma matriz de tamanho variável, você apenas usa um ponteiro, por exemplo

float *array;
array = (float *) calloc(sizeof(float), n);

Cria uma variedade de carros alegóricos de scripts singulares de tamanho n. Existe algo semelhante que eu possa fazer para matrizes duplamente com scripts?

Foi útil?

Solução

Não há matrizes com scripts duplos em c; Existem apenas matrizes de matrizes. Por exemplo, isso:

int a[3][3];

Deve ler como "Matriz de 3 matrizes de 3 ints", não como "matriz de 3x3 ints". Isso é imediatamente visível de tipos de expressões - por exemplo a[0] é uma expressão válida e seu tipo é int[3].

Para os tipos de matriz, o tamanho da matriz faz parte do tipo e, portanto, deve ser conhecido em tempo de compilação. Portanto, embora você possa ter um "ponteiro para matrizes" do tipo para tornar a dinâmica de uma dimensão, as restantes ainda precisariam ser consertadas:

int (*p)[3] // pointer to arrays of 3 ints each

Existem duas soluções alternativas tradicionais:

  1. Basta usar uma matriz dinâmica unidimensional de largura x altura elementos e calcule índices 1D de coordenadas 2D como (y * width + x) você mesma.

  2. Use ponteiro para ponteiros:

    int** a = malloc(sizeof(int*) * height);
    for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
    a[0][0] = 123;
    ...
    

    O problema aqui é que sua matriz não precisa mais ser retangular, e você não pode realmente aplicá -la. Em termos de desempenho, também é pior do que um único bloco de memória contígua.

No C99, você também pode usar matrizes de comprimento variável:

void foo(int width, int height) {
    int a[width][height];
    ...
}

Outras dicas

o Comp.lang.c FAQ tem uma boa seção sobre isso.

Você pode fazer quase a mesma coisa para matrizes multidimensionais.

float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
    array[i] = calloc(sizeof(float), n);
}

Se você deseja uma matriz com n linhas e M colunas, você pode usar uma matriz linear de comprimento m*n Para representar isso, onde cada índice i representa

row = i  / n
col = i  % n

e o mapeamento inverso

i  = row * n  + col

A maioria dos pacotes de álgebra que usam matrizes como o MATLAB realmente usa essa representação, porque generaliza bem para qualquer dimensão (você pode generalizá-lo para uma matriz tridimensional da mesma forma).

Não, isso não é possível. Como alternativa, aloque uma única matriz e defina uma função de indexação que pega sua coordenada e retorna um índice na matriz.

int Index(int i, int j, int numCols)
{ 
    return i * numCols + j;
}

int numRows = 100;
int numCols = 200;

float *data = malloc(sizeof(float) * numRows * numCols);

data[Index(34, 56, numCols)] = 42.0f;

Você pode usar matrizes de comprimento de variável C99 (obras com GCC):

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

void foo(size_t rows, size_t cols, float array[rows][cols])
{
    printf("%f\n", array[2][3]);
}

int main(void)
{
    size_t rows = 4;
    size_t cols = 5;
    float (*array)[cols] = calloc(sizeof (float), rows * cols);
    array[2][3] = 42;
    foo(rows, cols, array);
}

Estou surpreso que ninguém tenha apontado a alternativa "óbvia" que preserva a alocação contígua única para a matriz principal, mas tem o vetor de ponteiros para dar dupla assinatura. (Suponho que isso significa que não é óbvio, afinal.)

float **array2d = malloc(sizeof(*array2d) * height);
float  *array1d = malloc(sizeof(*array1d) * height * width);

for (i = 0; i < height; ++i)
    array2d[i] = &array1d[i * width];

Agora você pode escrever acessos de matriz 2-D como de costume:

array2d[0][0] = 123.0;

Claramente, também precisamos verificar a alocação de memória.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top