He leído en varios lugares que la asignación de matrices multidimensionales como tal es ineficiente y debe evitarse.
int main(){ int** arr2d = malloc(3*sizeof(int*)); for(int m = 0; m < 3 ; ++m){ arr2d[m] = malloc(sizeof(int)*3); } for(int m = 0 ; m < 3 ; ++m){ for(int n = 0; n < 3; ++n){ arr2d[m][n] = m+n; } } for(int m = 0 ; m < 3 ; ++m){ for(int n = 0; n < 3; ++n){ printf("%d,",arr2d[m][n]); } printf("\n"); } for(int m = 0; m < 3 ; ++m){ free(arr2d[m]); } free(arr2d); return 0; }La alternativa sería asignar una matriz suficiente para m * n e indexarla en consecuencia dando la idea de 2D
int main(){ int* arr = malloc(9*sizeof(int)); for(int m = 0; m < 3; ++m){ for(int n = 0; n < 3; ++n){ int index = m*3+n; arr[index] = m+n; } } for(int m = 0; m < 3; ++m){ for(int n = 0; n < 3; ++n){ int index = m*3+n; printf("%d,",arr[index]); } printf("\n"); } free(arr); return 0; }Lo que me pregunto es ¿cuánta diferencia en términos de uso de recursos y tiempo hace eso realmente? Sé que en el primer ejemplo se asignan un total de 32 bytes y en el segundo ejemplo se asignan 27 bytes. Cuando se trata de matrices mucho más grandes, puedo ver que marca la diferencia, pero ¿cambia la complejidad del tiempo o no importa ya que está haciendo un bucle m * n número de veces independientemente? ¿Debo seguir siempre el segundo ejemplo como básicamente estándar?
Puede obtener lo mejor de ambos mundos asignando memoria para una matriz multidimensional directamente:
int (*arr)[3] = malloc(3 * sizeof *arr); for(int m = 0 ; m < 3 ; ++m){ for(int n = 0; n < 3; ++n){ arr[m][n] = m+n; } } for(int m = 0 ; m < 3 ; ++m){ for(int n = 0; n < 3; ++n){ printf("%d,",arr[m][n]); } printf("\n"); } free(arr);Esto crea la memoria en un solo bloque contiguo como el segundo ejemplo, lo que permite lecturas y escrituras más eficientes, y le brinda una indexación de matriz 2D, lo que permite una lectura más fácil del código y permite que el compilador descubra la mejor manera de indexar en la memoria. bloquear internamente.
Si tiene una matriz rectangular, es decir, todos los valores mxn, entonces es menos tedioso, menos consumo de memoria y menos propenso a errores usar la segunda opción (aunque podría decirse que todavía es cuestión de gustos...).
La primera opción se vuelve más eficiente si no tiene algo rectangular, por ejemplo, algo así como una matriz de sub-matrices de diferentes longitudes.
El desperdicio de memoria puede volverse muy relevante allí.
Otro ejemplo, de regreso a las matrices, sería una matriz triangular, con 0 u otros valores conocidos fuera del triángulo. Las implementaciones podrían beneficiarse de ese atributo y usar los valores "aburridos" o predecibles desde fuera del triángulo, sin necesidad de almacenarlos.