How to create a matrix structure in C?


How to create a matrix structure in C?



I'm a beginner in C, but I'm currently trying to create a matrix data structure that could be used in different functions without having to explicitly pass the number of columns and number of rows (example: matrixMult(matrix A, matrix B) instead of matrixMult(A, B, rowsA, columnsA, rowsB, columnsB) ). My approach so far has been to declare a struct such as


matrixMult(matrix A, matrix B)


matrixMult(A, B, rowsA, columnsA, rowsB, columnsB)


typedef struct matrix{
int rows;
int columns;
int **data;
}matrix;



And then, to properly allocate the matrix, I'm trying to use the following function


matrix startmatrix(matrix mat,int n_row, int n_col){
int i=0;
mat.rows=n_row;
mat.columns=n_col;

mat.data=(int **) calloc(n_row,sizeof(int *));

for(i=0;i<n_row;i++){
mat.data[i]=(int *) calloc(n_col,sizeof(int));
}
return mat;
}



Which (to my understanding) allocates the rows containing the columns, and then allocates memory for the columns, which then contain the actual data.



The above part of the code seems to work fine, however when I try to input some data to the matrix and then visualize it later, e.g.:


A=startmatrix(A,2,3);
A.data[1,1]=1;
printf("%d",A.data[1,1]);



It returns a warning (assignment makes pointer from integer without a cast) and the number 4 inside the actual matrix.



Can anyone please explain what am I doing wrong?



EDIT: Adding the full code I'm using. So far it just consists of 2 files, mainfile.c and matrix.h. I also understand now (thanks!) that passing mat to startmatrix is useless and that i should use A.data, so I edited the code accordingly.
The main file is, so far:


mat


startmatrix


A.data


//Mainfile.c
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"


int main(){
matrix A=startmatrix(2,3); //2 by 3 matrix
A.data[1][1]=1; /*testing to see if the value 1 is passed to the first cell*/

printf("n%dn",A.rows); //Prints number of rows stored by A
printf("n%dn",A.columns); //Prints number of cols stored by A
printf("n%dnn",A.data[1][1]); //Is supposed to print the value stored in the first cell
return 0;
}



This calls the file "matrix.h", which contains the following (and the following only, so far)


#include <stdlib.h>

typedef struct matrix{
int rows, columns;
int **data;
}matrix;

matrix startmatrix(int n_row, int n_col){
matrix mat;
int i=0;
mat.rows=n_row;
mat.columns=n_col;

mat.data=(int **) calloc(n_row,sizeof(int *));

for(i=0;i<n_row;i++){
mat.data[i]=(int *) calloc(n_col,sizeof(int));
}
return mat;
}



So far, that is all the code I used for this problem, nothing more or less. I am reading the suggested answers and comments and trying them out, to see if they work. Thanks for the help, in advance.





You should look up how to use typedef with VLA, to access a malloced memory area as 2-dimensional array of any dimensions easily.
– hyde
Jul 1 at 15:26





You really don't need the first argument to startmatrix() — the number of rows and columns is sufficient information. You'd need to define a local matrix variable so you can return it, but that's not a big problem.
– Jonathan Leffler
Jul 1 at 19:07


startmatrix()


matrix





This answer should fit here. It answers your question
– Basile Starynkevitch
Jul 1 at 19:17






I'd go even further than Basile Starynkevitch, and suggest something similar to this. Not only does it allow rectangular two-dimensional matrices of any size, it allows you to create different matrices referring to the same actual data (row vectors, column vectors, diagonals, submatrices), and as long as you discard each matrix whenever you are done with them, the memory used by the data is managed for you.
– Nominal Animal
Jul 1 at 19:48





What happened in A.data[1,1]? 1,1 is a comma expression, which does not have the meaning for "row 1, column 1". So, even it seems to work, it's totally wrong.
– Stan
Jul 2 at 1:08


A.data[1,1]


1,1




2 Answers
2



As a beginner C programmer you should get to know and at least initially avoid complex cases of pointer arithmetic. For the matrix case you can actually do things simple. I took the liberty of adding very basic error detection using assert.


assert



To begin with, use single pointer when possible:


typedef struct matrix{
int rows;
int columns;
int *data;
}matrix;



Adapt your allocation procedure:


matrix startmatrix(int n_row, int n_col){
assert(n_row>0 && n_col>0);
matrix mat;
mat.rows=n_row;
mat.columns=n_col;
mat.data=calloc(n_row*n_col,sizeof(int)); /* allocate memory and clear to zero */
return mat; /* return copy of mat */
}



The prototype of this functions looked a little funny to me so I changed it a bit. It should have the same effect as the old one.



If you want to make the most of the structure, make accessor functions instead of working with the raw array index:


int* matrixcell(matrix mat, int column, int row){
assert(column < mat.columns && row < mat.rows);
return &mat.data[row*mat.columns + column]; /* pointer arithmetic */
}
/* example of using it */
*matrixcell(mat, 1, 1) = new_value;



The arithmetic is a very basic way of navigating through 2D data in a 1D array. Try it out on pen and paper, writing does the addresses of each cell. You'll see it makes sense.



You can't access a two dimensional array like that - C doesn't treat it as such, to the compiler it's just a pointer-to-pointer-to-integer. C also doesn't recognise the notation of multiple indexing (a number of indices separated with commas).



You should access the row with A.data[1], which gives you a pointer to the specific row, and then access the desired item in it - A.data[1][1].


A.data[1]


A.data[1][1]





Thanks, that's probably the correct way of doing things; but I tested it, and unfortunately now the program crashes when trying to assign the variables to the matrix structure. I think there's an error in the startmatrix function, but I'm not sure where.
– guscomm
Jul 1 at 15:17





@guscomm: That probably means you've got a separate problem that is now being exposed by fixing the first. Without code showing the second problem, there's not a lot anyone can do to help you.
– Jonathan Leffler
Jul 1 at 19:09







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages