0

I'm trying to store a series of matrices in a contiguous block of memory, and then retrieve them. Each array will be the same size (n x n).

As far as I understand, what I need to do is:

  1. Allocate and initialize each array that I need to store/retrieve.

  2. Allocate a contiguous block of memory of size (# arrays) * sizeof (1 array) and assign a pointer, ***matrices, to the beginning of the block

  3. Copy each array into the block at matrices[0], matrices[1], ...

  4. Print them by sending matrices[0], matrices[1], ... to a matrix_print function

Now, obviously I am misunderstanding something, because it isn't working. This is the output I get right before it crashes:

Matrix A is 16 bytes.
Matrix B is 16 bytes.
So, we will allocate 32 bytes in row_blocks.
Matrix A:
| 1  1 |
| 2  2 |
Matrix B:
| 2  2 |
|

Here is the code for my test case that I'm trying to get working:

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

void matrix_print(int dim, int ***matrix);
void matrix_init(int dim, int matrix[dim][dim], int val);

int main(int argc, char *argv[])
{
    int dim = 2;

    int A[dim][dim], B[dim][dim];

    matrix_init(dim, A, 1);
    matrix_init(dim, B, 2);

    printf("Matrix A is %d bytes.\n", sizeof A);
    printf("Matrix B is %d bytes.\n", sizeof B);

    int ***matrices = malloc(sizeof A + sizeof B);

    printf("So, we will allocate %d bytes in matrices.\n\n",
            sizeof A + sizeof B);

    memcpy(matrices[0], A, sizeof (A));
    memcpy(matrices[1], B, sizeof (B));

    printf("Matrix A:\n");
    matrix_print(dim, &matrices[0]);
    printf("Matrix B:\n");
    matrix_print(dim, &matrices[1]);

    return 0;
}

void matrix_print(int dim, int ***matrix)
{
    for (int i = 0; i < dim; i++) {
        printf("|");
        for (int j = 0; j < dim; j++) {
            printf("%2d ", matrix[i][j]);
        }
        printf("|\n");
     }
}

void matrix_init(int dim, int matrix[dim][dim], int val)
{
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            matrix[i][j] = val;
        }
     }
}

1 Answer 1

3

The joy of two-dimensional matrices in C!

When you pass a one-dimensional array int[dim] to a function, it decays into a pointer to its first element, int * or int[], losing the information on its size in the process.

A two-dimensional array int[dim][dim] does not decay into a double pointer, int **, but into a pointer to the first element of a row of size dim of ints, int (*)[dim] or int[][dim]. That is, because multi-dimensional arrays of constant row-size are treated specially; they are implemented as contiguous data blocks where the constant size is used to calculate the indices. (Constant here means constant for all rows and throughout all matrix operations; as in your case this value can be a variable in C99.)

Your matrices of type int[dim][dim] can't be represented as int **, so you should adjust the type of your matrix array:

int (*matrices)[dim][dim];

matrices = malloc(sizeof A + sizeof B);

The signature of your printing function also changes:

void matrix_print(int dim, int matrix[dim][dim])
{
    for (int i = 0; i < dim; i++) {
        printf("|");
        for (int j = 0; j < dim; j++) {
            printf("%2d ", matrix[i][j]);
        }
        printf("|\n");
     }
}

And you call it like this:

matrix_print(dim, matrices[0]);

without the address-of operator &.

Footnotes:

  • int (*x)[dim] is a pointer to an array of integer of length dim. int *x[dim] is an array of length dim of pointers to int.

  • The special treatment is owed to how Fortran stores multi-dimensional arrays, I think. If, on the other hand, you have allocated an array of pointers, they are int **. Such data structures can hold ragged matrices.

  • The matrices are C99-style arrays with variable lengths (VLA), which cannot be initialised, so the malloc has to be a separate declaration and assignment.

Sign up to request clarification or add additional context in comments.

1 Comment

Got it working, thank you so much. I had actually tried int *matrices[dim][dim] earlier and gotten confused because it wouldn't allow VLAs. It works with the parentheses though int *(matrices)[dim][dim]!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.