Arrays multidimensionales

Intermedio
C
C
Actualizado: 18/04/2026

Matriz bidimensional 3x3 con índices de fila y columna

Declaración e inicialización de arrays bidimensionales

Un array bidimensional es una estructura de datos que organiza sus elementos en filas y columnas, formando lo que en matemáticas se conoce como una matriz. A diferencia de los arrays unidimensionales, que representan una secuencia lineal de valores, los arrays de dos dimensiones permiten modelar tablas, cuadrículas, tableros de juego y cualquier tipo de dato con estructura rectangular.

La sintaxis general para declarar un array bidimensional en C es:

tipo nombre[filas][columnas];

Donde filas indica el número de filas y columnas el número de columnas. Cada combinación de fila y columna identifica un elemento concreto del array.

Inicialización con listas anidadas

La forma más habitual de inicializar una matriz es proporcionar los valores agrupados por filas mediante llaves anidadas:

int matriz[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

En este ejemplo se crea una matriz de 3 filas y 4 columnas. La primera llave interna corresponde a la fila 0, la segunda a la fila 1 y la tercera a la fila 2. Cada valor dentro de una llave interna ocupa una columna consecutiva.

Inicialización lineal

También es posible escribir todos los valores en una sola lista, sin llaves internas. El compilador distribuye los elementos fila a fila:

int matriz[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

El resultado es idéntico al caso anterior. Sin embargo, la versión con llaves anidadas resulta mucho más legible y es la práctica recomendada.

Inicialización parcial y a ceros

Si se proporcionan menos valores de los necesarios, las posiciones restantes se rellenan con cero de forma automática:

int tabla[2][3] = {
    {10, 20},
    {30}
};
// tabla[0][2] vale 0, tabla[1][1] vale 0, tabla[1][2] vale 0

Para inicializar toda la matriz a ceros basta con escribir:

int tabla[2][3] = {0};

Los arrays bidimensionales se almacenan en memoria de forma contigua, fila tras fila. La expresión tabla[i][j] accede al elemento situado en la fila i y la columna j, con ambos índices comenzando en 0.

Ejemplo práctico: tabla de notas

Supongamos que se desea almacenar las notas de 4 estudiantes en 3 asignaturas:

#include <stdio.h>

int main() {
    // 4 estudiantes, 3 asignaturas
    float notas[4][3] = {
        {7.5, 8.0, 6.5},
        {9.0, 7.2, 8.8},
        {5.5, 6.0, 7.0},
        {8.5, 9.5, 9.0}
    };

    // Mostrar la nota del estudiante 2 en la asignatura 3
    printf("Nota del estudiante 2, asignatura 3: %.1f\n", notas[1][2]);

    // Modificar una nota
    notas[2][0] = 6.0;
    printf("Nota corregida del estudiante 3, asignatura 1: %.1f\n", notas[2][0]);

    return 0;
}

Cada fila representa un estudiante y cada columna una asignatura, lo que facilita la organización y el acceso a los datos.

Recorrido de matrices con bucles anidados

Para procesar todos los elementos de un array bidimensional se utilizan bucles anidados: un bucle externo que itera sobre las filas y un bucle interno que itera sobre las columnas de cada fila. Esta combinación permite visitar cada celda de la matriz exactamente una vez.

Estructura general del recorrido

for (int i = 0; i < filas; i++) {
    for (int j = 0; j < columnas; j++) {
        // Operaciones con matriz[i][j]
    }
}

La variable i controla la fila actual y la variable j la columna. Para cada valor de i, el bucle interno recorre todas las columnas de esa fila antes de pasar a la siguiente.

Imprimir una matriz con formato tabular

#include <stdio.h>

int main() {
    int matriz[3][4] = {
        {1,  2,  3,  4},
        {5,  6,  7,  8},
        {9, 10, 11, 12}
    };

    int filas = 3;
    int columnas = 4;

    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < columnas; j++) {
            printf("%4d", matriz[i][j]);
        }
        printf("\n");
    }

    return 0;
}

La salida de este programa presenta los valores alineados en columnas gracias al formato %4d, que reserva 4 posiciones para cada número entero.

Sumar todos los elementos de una matriz

#include <stdio.h>

int main() {
    int datos[3][3] = {
        {10, 20, 30},
        {40, 50, 60},
        {70, 80, 90}
    };

    int suma = 0;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            suma += datos[i][j];
        }
    }

    printf("La suma de todos los elementos es: %d\n", suma);

    return 0;
}

Calcular el promedio por filas

Un caso frecuente consiste en calcular estadísticas por fila, por ejemplo el promedio de notas de cada estudiante:

#include <stdio.h>

int main() {
    float notas[3][4] = {
        {7.5, 8.0, 6.5, 9.0},
        {5.5, 6.0, 7.0, 8.0},
        {9.0, 8.5, 9.5, 10.0}
    };

    for (int i = 0; i < 3; i++) {
        float suma = 0;
        for (int j = 0; j < 4; j++) {
            suma += notas[i][j];
        }
        float promedio = suma / 4;
        printf("Estudiante %d: promedio = %.2f\n", i + 1, promedio);
    }

    return 0;
}

Cada iteración del bucle externo acumula los valores de una fila completa y calcula el promedio antes de avanzar a la siguiente fila.

Buscar un valor en una matriz

#include <stdio.h>

int main() {
    int tablero[3][3] = {
        {5, 12, 3},
        {8, 7, 15},
        {20, 1, 9}
    };

    int objetivo = 15;
    int encontrado = 0;

    for (int i = 0; i < 3 && !encontrado; i++) {
        for (int j = 0; j < 3 && !encontrado; j++) {
            if (tablero[i][j] == objetivo) {
                printf("Valor %d encontrado en la posicion [%d][%d]\n", objetivo, i, j);
                encontrado = 1;
            }
        }
    }

    if (!encontrado) {
        printf("El valor %d no se encuentra en la matriz\n", objetivo);
    }

    return 0;
}

La variable encontrado actúa como bandera para detener ambos bucles en cuanto se localiza el elemento buscado.

Cuando se trabaja con matrices cuadradas (mismo número de filas y columnas), la diagonal principal está formada por los elementos donde el índice de fila coincide con el índice de columna, es decir, matriz[i][i].

Paso de arrays multidimensionales a funciones

Pasar un array bidimensional como argumento a una función requiere conocer una regla esencial del lenguaje C: en la declaración de parámetros, es obligatorio especificar el tamaño de las columnas. La primera dimensión (filas) puede omitirse, pero las restantes deben estar explícitamente indicadas para que el compilador calcule correctamente las direcciones de memoria.

Sintaxis del parámetro

void procesarMatriz(int matriz[][4], int filas) {
    // Se sabe que cada fila tiene 4 columnas
}

El parámetro int matriz[][4] indica que se recibe un array cuyas filas tienen exactamente 4 columnas. El número de filas se pasa como argumento adicional porque, al decaer el array a puntero, esa información se pierde.

Ejemplo completo: imprimir una matriz desde una función

#include <stdio.h>

#define COLS 4

void imprimirMatriz(int mat[][COLS], int filas) {
    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%4d", mat[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int datos[3][COLS] = {
        {1,  2,  3,  4},
        {5,  6,  7,  8},
        {9, 10, 11, 12}
    };

    imprimirMatriz(datos, 3);

    return 0;
}

El uso de la constante COLS definida con #define garantiza que tanto la declaración del array como el parámetro de la función compartan el mismo valor, evitando errores difíciles de detectar.

Función que calcula la suma de una columna

#include <stdio.h>

#define FILAS 3
#define COLS  4

int sumaColumna(int mat[][COLS], int filas, int columna) {
    int suma = 0;
    for (int i = 0; i < filas; i++) {
        suma += mat[i][columna];
    }
    return suma;
}

int main() {
    int ventas[FILAS][COLS] = {
        {120, 200, 150, 180},
        {90,  310, 275, 160},
        {210, 180, 195, 220}
    };

    for (int j = 0; j < COLS; j++) {
        printf("Suma de la columna %d: %d\n", j, sumaColumna(ventas, FILAS, j));
    }

    return 0;
}

La función sumaColumna recibe la matriz, el número de filas y el índice de la columna a sumar. Esto la hace reutilizable para cualquier columna de la tabla.

Función que busca el valor máximo

#include <stdio.h>

#define COLS 3

int buscarMaximo(int mat[][COLS], int filas) {
    int maximo = mat[0][0];

    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < COLS; j++) {
            if (mat[i][j] > maximo) {
                maximo = mat[i][j];
            }
        }
    }

    return maximo;
}

int main() {
    int temperaturas[4][COLS] = {
        {22, 25, 20},
        {30, 28, 27},
        {18, 19, 21},
        {26, 31, 29}
    };

    printf("Temperatura maxima registrada: %d\n", buscarMaximo(temperaturas, 4));

    return 0;
}

Al pasar un array multidimensional a una función, no se copia la matriz completa. La función recibe un puntero al primer elemento, por lo que cualquier modificación realizada dentro de la función afecta directamente al array original.

Aplicaciones prácticas con matrices

Las matrices permiten resolver de forma natural problemas que implican datos organizados en dos dimensiones. A continuación se presentan varios ejemplos habituales en cursos de programación y en el desarrollo de aplicaciones reales.

Transposición de una matriz

La transpuesta de una matriz se obtiene intercambiando filas por columnas. El elemento que estaba en la posición [i][j] pasa a la posición [j][i]:

#include <stdio.h>

#define N 3

void transponer(int origen[][N], int destino[][N]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            destino[j][i] = origen[i][j];
        }
    }
}

void imprimir(int mat[][N]) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            printf("%4d", mat[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int original[N][N] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    int transpuesta[N][N];

    transponer(original, transpuesta);

    printf("Matriz original:\n");
    imprimir(original);

    printf("\nMatriz transpuesta:\n");
    imprimir(transpuesta);

    return 0;
}

La función transponer copia cada elemento de origen[i][j] en destino[j][i], generando la matriz transpuesta en un array independiente.

Suma de dos matrices

Sumar dos matrices consiste en sumar elemento a elemento las posiciones correspondientes:

#include <stdio.h>

#define FILAS 2
#define COLS  3

void sumarMatrices(int a[][COLS], int b[][COLS], int resultado[][COLS], int filas) {
    for (int i = 0; i < filas; i++) {
        for (int j = 0; j < COLS; j++) {
            resultado[i][j] = a[i][j] + b[i][j];
        }
    }
}

int main() {
    int matA[FILAS][COLS] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    int matB[FILAS][COLS] = {
        {10, 20, 30},
        {40, 50, 60}
    };

    int matR[FILAS][COLS];

    sumarMatrices(matA, matB, matR, FILAS);

    printf("Resultado de la suma:\n");
    for (int i = 0; i < FILAS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%4d", matR[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Multiplicación de matrices

La multiplicación de matrices es una operación algebraica donde cada elemento del resultado se calcula como el producto escalar de una fila de la primera matriz por una columna de la segunda:

#include <stdio.h>

#define M 2
#define N 3
#define P 2

void multiplicar(int a[][N], int b[][P], int resultado[][P]) {
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < P; j++) {
            resultado[i][j] = 0;
            for (int k = 0; k < N; k++) {
                resultado[i][j] += a[i][k] * b[k][j];
            }
        }
    }
}

int main() {
    // Matriz A de 2x3
    int a[M][N] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    // Matriz B de 3x2
    int b[N][P] = {
        {7,  8},
        {9,  10},
        {11, 12}
    };

    // Resultado de 2x2
    int resultado[M][P];

    multiplicar(a, b, resultado);

    printf("Producto de matrices:\n");
    for (int i = 0; i < M; i++) {
        for (int j = 0; j < P; j++) {
            printf("%4d", resultado[i][j]);
        }
        printf("\n");
    }

    return 0;
}

Se necesitan tres bucles anidados: los dos primeros seleccionan la posición del resultado y el tercero acumula los productos parciales.

Tablero de tres en raya

Las matrices son la estructura natural para representar tableros de juego. Este ejemplo modela un tablero de tres en raya y comprueba si alguna fila tiene tres marcas iguales:

#include <stdio.h>

#define TAM 3

void mostrarTablero(char tablero[][TAM]) {
    for (int i = 0; i < TAM; i++) {
        for (int j = 0; j < TAM; j++) {
            printf(" %c ", tablero[i][j]);
            if (j < TAM - 1) printf("|");
        }
        printf("\n");
        if (i < TAM - 1) printf("-----------\n");
    }
}

int comprobarFilas(char tablero[][TAM]) {
    for (int i = 0; i < TAM; i++) {
        if (tablero[i][0] != ' ' &&
            tablero[i][0] == tablero[i][1] &&
            tablero[i][1] == tablero[i][2]) {
            printf("Ganador en fila %d: %c\n", i, tablero[i][0]);
            return 1;
        }
    }
    return 0;
}

int main() {
    char tablero[TAM][TAM] = {
        {'X', 'O', 'X'},
        {'O', 'X', 'O'},
        {'X', 'X', 'X'}
    };

    mostrarTablero(tablero);
    printf("\n");

    if (!comprobarFilas(tablero)) {
        printf("Ninguna fila completa\n");
    }

    return 0;
}

El tablero se almacena como una matriz de caracteres de 3x3. La función comprobarFilas recorre cada fila verificando si las tres celdas contienen el mismo carácter distinto de espacio.

Arrays de tres dimensiones

C permite declarar arrays con más de dos dimensiones. Un array tridimensional puede verse como un conjunto de matrices apiladas, útil para representar datos que varían según tres ejes. Por ejemplo, las temperaturas de varias ciudades a lo largo de varios días y franjas horarias:

#include <stdio.h>

int main() {
    // 2 ciudades, 3 dias, 4 franjas horarias
    float temperaturas[2][3][4] = {
        {
            {15.0, 20.5, 25.0, 18.0},
            {14.5, 19.0, 24.5, 17.5},
            {16.0, 21.0, 26.0, 19.0}
        },
        {
            {10.0, 15.5, 20.0, 13.0},
            {11.0, 16.0, 21.5, 14.0},
            {9.5, 14.5, 19.0, 12.5}
        }
    };

    char *ciudades[] = {"Madrid", "Burgos"};

    for (int c = 0; c < 2; c++) {
        printf("Ciudad: %s\n", ciudades[c]);
        for (int d = 0; d < 3; d++) {
            printf("  Dia %d:", d + 1);
            for (int h = 0; h < 4; h++) {
                printf(" %.1f", temperaturas[c][d][h]);
            }
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}

Se necesitan tres bucles anidados para recorrer todas las celdas. El principio es el mismo que con dos dimensiones, pero se añade un nivel adicional de iteración por cada dimensión extra.

En la práctica, rara vez se utilizan más de tres dimensiones. Cuando un problema exige más niveles de anidamiento, suele ser preferible reorganizar los datos usando estructuras (struct) o punteros a arrays para mantener la legibilidad del código.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, C es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de C

Explora más contenido relacionado con C y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Declarar e inicializar arrays de dos y más dimensiones. Recorrer matrices con bucles anidados. Pasar arrays multidimensionales a funciones. Aplicar matrices en problemas prácticos como tablas y tableros.

Cursos que incluyen esta lección

Esta lección forma parte de los siguientes cursos estructurados con rutas de aprendizaje