This demonstrates VLAs (variable length arrays) at work. It is based on code for SO 32565694, which asked about VLAs in structures. This code avoids using structures.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int nr, nc;
void *data; // Actually double a[nr][nc]
} Matrix;
static double variant1(int nr, int nc, int r, int c)
{
assert(nr != 0);
return (r * nc) + c + 1;
}
static double variant2(int nr, int nc, int r, int c)
{
return ((nr - r) * nc) + (nc - c) + 1;
}
typedef double (*Initializer)(int nr, int nc, int r, int c);
static void mat_init(int nr, int nc, double m[nr][nc], Initializer init)
{
assert(m != 0 && nr > 0 && nc > 0);
printf("Set: [%dx%d]\n", nr, nc);
for (int i = 0; i < nr; i++)
{
printf("[%d]:", i);
for (int j = 0; j < nc; j++)
{
double v = init(nr, nc, i, j);
m[i][j] = v;
printf(" %6.1f", v);
}
putchar('\n');
}
}
static void mat_dump(const char *tag, int nr, int nc, double m[nr][nc])
{
assert(m != 0 && nr > 0 && nc > 0);
printf("Matrix %s: %dx%d\n", tag, nr, nc);
for (int i = 0; i < nr; i++)
{
printf("[%d]:", i);
for (int j = 0; j < nc; j++)
printf(" %6.1f", m[i][j]);
putchar('\n');
}
}
static void mat_multiply(int r1, int c1, double m1[r1][c1],
int r2, int c2, double m2[r2][c2],
int r3, int c3, double m3[r3][c3])
{
assert(r1 > 0 && c1 > 0 && r2 > 0 && c2 > 0 && r3 > 0 && c3 > 0);
printf("m1[%d][%d] x m2[%d][%d] = m3[%d][%d]\n", r1, c1, r2, c2, r3, c3);
assert(r1 == r3 && c2 == c3 && c1 == r2);
for (int i = 0; i < r1; i++)
{
for (int j = 0; j < c2; j++)
{
double sum = 0.0;
for (int k = 0; k < c1; k++)
sum += m1[i][k] * m2[k][j];
m3[i][j] = sum;
}
}
}
int main(void)
{
int r1 = 3;
int c1 = 5;
int r2 = c1;
int c2 = 4;
int r3 = r1;
int c3 = c2;
double m1[r1][c1];
double m2[r2][c2];
double m3[r3][c3];
printf("m1:\n");
mat_init(r1, c1, m1, variant1);
printf("m2:\n");
mat_init(r2, c2, m2, variant2);
mat_dump("m1", r1, c1, m1);
mat_dump("m2", r2, c2, m2);
mat_multiply(r1, c1, m1, r2, c2, m2, r3, c3, m3);
mat_dump("m3", r3, c3, m3);
return 0;
}
Example output:
m1:
Set: [3x5]
[0]: 1.0 2.0 3.0 4.0 5.0
[1]: 6.0 7.0 8.0 9.0 10.0
[2]: 11.0 12.0 13.0 14.0 15.0
m2:
Set: [5x4]
[0]: 25.0 24.0 23.0 22.0
[1]: 21.0 20.0 19.0 18.0
[2]: 17.0 16.0 15.0 14.0
[3]: 13.0 12.0 11.0 10.0
[4]: 9.0 8.0 7.0 6.0
Matrix m1: 3x5
[0]: 1.0 2.0 3.0 4.0 5.0
[1]: 6.0 7.0 8.0 9.0 10.0
[2]: 11.0 12.0 13.0 14.0 15.0
Matrix m2: 5x4
[0]: 25.0 24.0 23.0 22.0
[1]: 21.0 20.0 19.0 18.0
[2]: 17.0 16.0 15.0 14.0
[3]: 13.0 12.0 11.0 10.0
[4]: 9.0 8.0 7.0 6.0
m1[3][5] x m2[5][4] = m3[3][4]
Matrix m3: 3x4
[0]: 215.0 200.0 185.0 170.0
[1]: 640.0 600.0 560.0 520.0
[2]: 1065.0 1000.0 935.0 870.0
It would be perfectly feasible to use command line arguments or user input to set the values of r1
, c1
(or r2
) and c2
(but the values in r2
(or c1
), r3
and c3
are constrained, for this code, by r1
, c1
and c2
). The initialization code would work fine, and so would the multiplication.