Pregunta

¿Hay alguna forma de crear una matriz de doble script de tamaño variable en C (no C ++, solo C)? Sé que para crear una matriz de un solo script de tamaño variable, solo usa un puntero, por ejemplo,

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

crea una matriz de scripts flotantes de tamaño n. ¿Hay algo similar que pueda hacer para matrices con doble script?

¿Fue útil?

Solución

No hay matrices de doble script en C; solo hay matrices de matrices. P.ej. esto:

int a[3][3];

Debería leerse como "matriz de 3 matrices de 3 pulgadas", no como "matriz de 3x3 pulgadas". Esto es inmediatamente visible desde los tipos de expresiones, p. Ej. a [0] es una expresión válida y su tipo es int [3] .

Para los tipos de matriz, el tamaño de la matriz es parte del tipo y, por lo tanto, debe conocerse en tiempo de compilación. Por lo tanto, si bien puede tener un tipo '' puntero a matrices '' para dinamizar una dimensión, las restantes aún tendrían que repararse:

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

Hay dos soluciones tradicionales:

  1. Simplemente use una matriz dinámica unidimensional de elementos ancho x alto , y calcule índices 1D a partir de coordenadas 2D como (y * ancho + x) usted mismo.

  2. Use el puntero a los punteros:

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

    El problema aquí es que su matriz ya no necesita ser rectangular, y realmente no puede forzarla. En cuanto al rendimiento, también es peor que un solo bloque contiguo de memoria.

En C99, también puede usar matrices de longitud variable:

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

Otros consejos

Las comp.lang.c FAQ tiene una buena sección sobre esto.

Puede hacer casi lo mismo para arreglos multidimensionales.

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

Si desea una matriz con n filas ym columnas, puede usar una matriz lineal de longitud m * n para representar esto, donde cada índice i representa

row = i  / n
col = i  % n

y el mapeo inverso

i  = row * n  + col

La mayoría de los paquetes de álgebra que usan matrices como matlab en realidad usan esta representación, porque se generaliza bien a cualquier dimensión (también podría generalizar esto a una matriz tridimensional).

No, eso no es posible. Como alternativa, asigne una única matriz y defina una función de indexación que tome su coordenada y devuelva un índice a la 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;

Puede usar matrices de longitud variable C99 (funciona con 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);
}

Me sorprende que nadie haya señalado la alternativa 'obvia' que conserva la asignación contigua única para la matriz principal, pero tiene el vector de punteros para dar doble subíndice. (Supongo que eso significa que no es obvio, después de todo).

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

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

Ahora puede escribir accesos de matriz 2-D como de costumbre:

array2d[0][0] = 123.0;

Claramente, también necesitamos verificar la asignación de memoria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top