Evan Kim
Evan Kim

Reputation: 829

Create a variable size matrix

I am trying to create a variable matrix using a function that inputs an empty array pointer m and outputs the int array pointer m with values 1,2,3,4,...n elements in the matrix. I use the variable k and increment the value upwards to accomplish this (not sure if this is the best way).

I am getting a subscripted value is not an array, pointer, or vector in my for loop here matrix[i][j] = k++; and I am not really sure why it is only appearing inside the for loop and nowhere else.

If I am inputting an int array pointer called matrix, I shouldn't be getting this error right?

int *create_matrix(int* matrix) {
    int i,j;
    int k = 0;

    // 'total' will be 70 = 10 * 7
    int total = sizeof(matrix);

    // 'column' will be 7 = size of first row
    int column = sizeof(matrix[0]);

    // 'row' will be 10 = 70 / 7
    int row = total / column;


    for (i=0; i < row; i++) {
        for (j=0; j < column; j++) {
            matrix[i][j] = k++;
        }
    }
    return matrix;
}

int main(void) {

    // Creating a custom matrix.
    int m[3][4] = {0};
    create_matrix(*m);
    return 0;
}

Upvotes: 1

Views: 754

Answers (3)

thb
thb

Reputation: 14434

Your attempt is a reasonable attempt but it reveals some misconceptions about how objects in C work. That's all right. Yours is a good teaching example and I believe that you will be glad that you have made it. Now try this:

static const int NO_ROWS    = 3;
static const int NO_COLUMNS = 4;

int *create_matrix(
  int *const matrix, const int no_rows, const int no_columns
) {
    int k = 0;
    for (int i = 0; i < no_rows; i++) {
        for (int j = 0; j < no_columns; j++) {
            matrix[no_columns*i+j] = k++;
        }
    }
    return matrix;
}

int main(void) {
    // Creating a custom matrix.
    int m[NO_ROWS][NO_COLUMNS];
    create_matrix(m[0], NO_ROWS, NO_COLUMNS);
    return 0;
}

Your matrix is constructed as an array of arrays. However, in C, an array is just a region of storage in which a sequence of objects of the same type (in your case, int) can be kept. The symbol m is interpreted by the C compiler as

  • meaning the address of the matrix's initial element—or, more precisely, because your matrix is an array of arrays, the address of the matrix's initial row; and
  • referring to the type of the matrix's initial row, which is itself an array type, int[NO_COLUMNS].

The problem is that there exists no really neat, direct way to specify to a precompiled function the type int[NO_COLUMNS] unless you are willing to hard-code the type. Therefore, one relatively straightforward way to treat the matrix within create_matrix() would be as a single, linear array, as shown.

One point to grasp here is that C does not understand the shape of your matrix. Rather than rows and columns, C sees a linear region of storage.

Another point to grasp is that function to which an array is passed receives only the array's initial address. If it needs the size, that must be separately passed.

Upvotes: 0

bruno
bruno

Reputation: 32586

To do

int m[3][4] = {0};
create_matrix(*m);

is equivalent of

int m[3][4] = {0};
create_matrix(m[0]);

so is equivalent of having

int m[4] = {0};
create_matrix(m);

// 'total' will be 70 = 10 * 7
int total = sizeof(matrix);

matrix is a int *, sizeof(matrix) values 4 if an address uses 32b and 8 if an address uses 64b

The effective size of matrix in main is not relevant


// 'column' will be 7 = size of first row
int column = sizeof(matrix[0]);

matrix[0] is an int, so you get the size of an int (4 or 8 probably)


matrix[i][j] = k++;

because matrix is an int * the form matrix[i][j] is invalid.

To name it matrix is not helpful.


Your program can be :

#include <stdio.h>

void fill_matrix(int matrix[][4], size_t row) {
  size_t i, j;
  int k = 0;

  for (i=0; i < row; i++) {
    for (j=0; j < sizeof(matrix[0])/sizeof(int); j++) {
      matrix[i][j] = k++;
    }
  }
}

int main(void) {

  // Creating a custom matrix.
  int m[3][4] = {0};

  fill_matrix(m, sizeof(m)/sizeof(m[0]));

  size_t i, j;

  for (i=0; i < sizeof(m)/sizeof(m[0]); i++) {
    for (j=0; j < sizeof(m[0])/sizeof(int); j++) {
      printf("matrix[%d][%d] = %d\n", i, j, m[i][j]);
    }
  }


  return 0;
}

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra m.c
pi@raspberrypi:/tmp $ ./a.out
matrix[0][0] = 0
matrix[0][1] = 1
matrix[0][2] = 2
matrix[0][3] = 3
matrix[1][0] = 4
matrix[1][1] = 5
matrix[1][2] = 6
matrix[1][3] = 7
matrix[2][0] = 8
matrix[2][1] = 9
matrix[2][2] = 10
matrix[2][3] = 11

Probably it is more visible if you initialize each cell of the matrix with i*10+j rather than with k++, in that case that prints :

matrix[0][0] = 0
matrix[0][1] = 1
matrix[0][2] = 2
matrix[0][3] = 3
matrix[1][0] = 10
matrix[1][1] = 11
matrix[1][2] = 12
matrix[1][3] = 13
matrix[2][0] = 20
matrix[2][1] = 21
matrix[2][2] = 22
matrix[2][3] = 23

Upvotes: 1

klutt
klutt

Reputation: 31296

You need to learn the difference between arrays and pointers. You can point a pointer to a matrix, but the information about size and number of dimensions are lost as long as you're only accessing the array via the pointer.

You would need to do something like this:

int *create_matrix(int* matrix, size_t size_x, size_t size_y) {
   ...
}

int main()
{
    int m[3][6];
    size_t size_y=sizeof m[0]/sizeof m[0][0];
    size_t size_x=sizeof m / sizeof m[0];
    create_matrix(m);
}

Upvotes: 1

Related Questions