Categorías: Tutoriales

Reservar memoria dinámica para una matriz en C

Acabamos de hablar hace nada de cómo reservar memoria para un vector unidimensional de forma dinámica con C. Hoy le toca el turno a las matrices o arrays bidimensionales. Los vectores se organizan de forma lineal, secuencial y con todos los elementos en posiciones correlativas en la memoria. Las matrices se almacenan en forma de vector de vectores.

Dimensiones fijas

Si es de dimensiones fijas (declarándolas como matriz[filas][columnas]), el vector de vectores se guardará también uno al lado del otro.

Por lo tanto, en una matriz del tipo:

a00 a01 a02
a10 a11 a12
a20 a21 a22

En memoria (en la que los elementos los direccionamos en una sola dirección) los tendríamos de la siguiente forma (en cada lenguaje este criterio cambia, en Fotran se almacena en forma de vector de columnas):

a00 a01 a02 a10 a11 a12 a20 a21 a22

Dimensiones variables

Sin embargo, en el caso de la memoria dinámica, las cosas cambian. El mecanismo será el siguiente:

  • Declararemos un doble puntero “matriz” sobre el que reservaremos memoria para tantas filas tengamos.
  • Recorreremos el vector recién creado para reservar memoria para las columnas de cada fila.

Hay dos detalles a tener en cuenta:

  • La variable “matriz” será del tipo doble puntero ya que hará referencia a un vector de punteros.
  • Cada fila sí estará almacenada de forma consecutiva en memoria, pero éstas a su vez no estarán de forma obligada juntas, aunque podremos seguir accediendo de la misma forma.

Veamos un ejemplo con código real (no hace comprobaciones de que el malloc se ejecute correctamente):

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

int main(void) 
{ 

 int filas = 2;
 int columnas = 3; 
 int **x; 

 int i;  // Recorre filas 
 int j;  // Recorre columnas 

 // Reserva de Memoria 
 x = (int **)malloc(filas*sizeof(int*)); 
 
 for (i=0;i<filas;i++) 
  x[i] = (int*)malloc(columnas*sizeof(int)); 

 // Damos Valores a la Matriz 
 x[0][0] = 1; 
 x[0][1] = 2; 
 x[0][2] = 3; 

 x[1][0] = 4; 
 x[1][1] = 5; 
 x[1][2] = 6; 

 // Dibujamos la Matriz en pantalla 
 for (i=0; i<filas; i++) 
 { 
  printf("\n"); 
  for (j=0; j<columnas; j++) 
   printf("\t%d", x[i][j] ); 
 } 
 
 return 0; 
} 
F. Javier Carazo Gil

Cofundador de CODECTION, empresa especializada en WordPress, autor de un libro sobre WordPress (el primero en español) y multitud de artículos (en medios físicos y virtuales) sobre el tema. Participa en la comunidad WordPress de forma activa siendo parte del equipo organizador de la WordPress Meetup de Córdoba, dando charlas en diferentes WordCamp y siendo autor y coautor de multitud de plugins libres y premium para WordPress de gran éxito.

Ver comentarios

  • En tu ejemplo, CREO, que la tabla no estaría en posiciones consecutivas. Para lograrlo, y teniendo en cuenta que las dimensiones las conocemos podríamos hacer algo así:

    x[0]=(int*)malloc(filas*columnas*sizeof(int)); //reserva espacio para toda la tabla
    for (i=1;i<filas;i++) //apuntar a cada fila (la 0 ya está)
    x[i] = x[i-1]+columnas;

    Bueno, la verdad es que no estoy muy seguro, tengo el tema un poco oxidado... Haber si alguien lo puede confirmar.
    Un saludo, y a seguir disfrutando del verano. ¡Que poco queda!

  • @Miguel: En mi ejemplo, sólo estaría en posiciones correlativas los vectores que reservo en la iteración, pero cada vector de estos no estarían juntos.

    Creo que lo que planteas no funcionaría pero no te lo sé decir a ciencia cierta. ¿Alguien puede sacarnos de dudas? Podríamos hacer el ejemplo y compilarlo... si tengo tiempo lo hago y os lo cuento.

    La única manera en la que sé seguro que sí están juntos es declarándola estáticamente.

  • Lo que dice Miguel funciona, pero para aclararlo expongo el código a sustituir:
    // Reserva de Memoria
    x = (int **)malloc(filas*sizeof(int*));

    for (i=0;i<filas;i++)
    x[i] = (int*)malloc(columnas*sizeof(int));

    Y se cambiaría por:
    x = (int **)malloc(filas*sizeof(int*)); //reserva para punteros a cada fila

    x[0]=(int*)malloc(filas*columnas*sizeof(int)); //reserva para datos de la tabla
    for (i=1;i<filas;i++) //apuntar a cada fila (la 0 ya está)
    x[i] = x[i-1]+columnas; //punt_fila_siguiente=punt_fila_anterior + columnas

    Hasta la próxima...

  • Hola soy estudiante de primer año y me dejaron de tarea crear un programa en c++ con new y delate que se ocupe de reservar toda la memoria RAM, y me gustaria que alguien me de alga guia o masomenos como le haria

  • @Hola Una duda: En C++ tenemos el operador que se le pasa el tipo y el número de elementos a reservar.

    Si tu memoria es de 1GB podrías hacer new char[1024*1024*1024], no sé si habrá un problema por representar un entero tan largo (si lo hay hazlo mediante tres bucles de 1024 por ejemplo). Ten en cuenta que 1GB son 1024MB y a su vez 1MB son 1024KB y 1KB son 1024B que casi con total seguridad son lo que ocupa un char en tu compilador/arquitectura.

    Puedes hacer sizeof para asegurarte.

    Lo que sí es cierto es que reservaras una cantidad de memoria equivalente a toda tu RAM pero como habrá cosas cargadas, el sistema operativo se encargará de pedir memoria virtual.

    • Existe un método free() que es justo para eso. Se aplica sobre un puntero y en este caso deberías aplicarlo primero por cada x[i] y luego sobre x.

      Cuando el proceso termina, el sistema operativo, si no has liberado la memoria, la libera él.

  • Yo lo resolví de esta forma. declare una estructura (q genera un nuevo tipo de variable , q llame "matriz")que contiene un arreglo bidimensional, luego creo una variable de tipo puntero a "matriz" y con malloc obtengo un punteo al primer lugar de memoria. Para acceder a las filas y columnas lo hago como se hace comúnmente con estructuras. Les dejo el programa.

    #include
    #include

    typedef struct
    {

    int mat[5][5];

    }matriz;

    int main(void)
    {

    matriz *tre=(matriz*)malloc(sizeof(matriz));
    int i,j;

    srand(time(NULL));

    for(i=0;i<5;i++)
    for(j=0;jmat[i][j]=rand()%100;

    for(i=0;i<5;i++)
    {
    for(j=0;jmat[i][j]);
    printf("n");

    }

    free(tre);

    return 0;

    }

    Les dejo el link de un blog de programacion que estoy armando: http://comoseprogramaenc.blogspot.com.ar/

    • No te sirve de nada eso porque conoces el tamaño de antemano de las filas y columnas. La función free le pide al sistema operativo que asigne memoria disponible en tiempo de ejecución. Tu programa lo hace en la compilación, eso quiere decir que siempre ocupará la misma memoria. En este programa que subió el amigo el tamaño de filas y columnas puede varias en tiempo de ejecución y no desbordará la memoria como el código que hiciste si lo intentas hacer en tiempo de ejecución.

Entradas recientes

DeepSeek

2 días hace

Contacto

2 semanas hace

Smart-tv mute

2 semanas hace

STEAM OS

3 semanas hace

2025

4 semanas hace

El podcast de Linux Hispano – #072 – El hardware libre debe consolidarse como el software libre

https://www.youtube.com/embed/z-xGk9c_eOw Guionista y locutor: Manuel Ignacio López Quintero.Fecha de publicación: 31 de diciembre de 2024.

1 mes hace