C - address of matrix as an argument in function - c

I have this header:
#define SIZE 4
typedef float matrix[SIZE][SIZE];
typedef struct {
char *name;
matrix *mat;
} matRec;
void printMat(matrix *);
void read_mat(matrix , float []);
declaration in the main:
matrix m[6];
matRec mats[6] = {
{"MAT_A", &m[0]},
{"MAT_B", &m[1]},
{"MAT_C", &m[2]},
{"MAT_D", &m[3]},
{"MAT_E", &m[4]},
{"MAT_F", &m[5]}
};
struct {
char *name;
void (*func)();
} cmd[] = {
{"read_mat", read_mat},
{"not_valid", NULL}
};
this is also part of my main:
(*(cmd[func].func))(&mats[matrixx].mat, num);
printMat(mats[matrixx].mat);
my printMat function in the main:
void printMat(matrix *matrx) {
int i,j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
printf("%7f ", matrx[i][j]);
}
printf("\n");
}
printf("\n");
}
and the read_mat function (in another file):
void read_mat(matrix matrx, float num[]) {
int i, j, count = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
matrx[i][j] = num[count];
count++;
}
}
}
My purpose is to send an address of my matrix from array: mats, with array of float numbers, insert them, and print the matrix with another function. I have difficulties in sending the address. The read_mat function does "work", but with a copy of matrix(in the scope of the function), then obviously prints matrix with only zeros. I don't understand how to write the right types of arguments with pointers in declaration of function. Any other combination of * gives error. THANKS

I guess few of the type information would help you. Here by saying this
matrix m[6];
You are basically declaring
float m[6][SIZE][SIZE];
And then type of m[0] is nothing but float [SIZE][SIZE] or matrix.
So when I pass it's address to a function it would be
somefun(&m[0]);
You would declare and use it like this
..somefun(matrix *t){
for(int i = 0; i< SIZE; i++)
for(int j =0 ; j< SIZE; j++)
printf("%lf",(*t)[i][j]);
..
}

Related

passing a char 2d array into a void function in c

I'm new to c but I have been trying for ages to try and get this to work even though it seems so simple.
So below is what I am aiming to do which is working but I want to make 2 functions: fillseats() and printseatingplan()[for now I just want them all blank];
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char seatingplan[15][15];
memset(seatingplan,'.',sizeof seatingplan);
for (int k = 0; k < 15; ++k)
{
for(int j = 0; j < 15; ++j)
{
printf("%c",seatingplan[k][j]);
}
printf("\n");
}
}
So whenever I try to run these functions without pointers it gives me these �`:�ij:�
i�d:�iH#=�i
�B��ik:�
how can i use pointers to fix this
can I pass this array into the functions where printseatingplan()
void printseatingplan(char array[15][15])
{
for (int k = 0; k < 15; ++k)
{
for(int j = 0; j < 15; ++j)
{
printf("%c",array[k][j]);
}
printf("\n");
}
}
and then fillseats() does:
void fillseats(char array[15][15])
{
memset(array,'.',sizeof array);
}
sizeof will give you only the size of the pointer, not the whole array.
You need to pass the sizes to the function. I would use pointer to array:
void fillseats(size_t rows, size_t cols, char (*array)[cols])
{
memset(array,'.',rows * sizeof(*array));
}
void printseatingplan(size_t rows, size_t cols, char (*array)[cols])
{
for (size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
printf("%c",array[row][col]);
}
printf("\n");
}
}
char array[15][15] when used as parameter to a function "decays" into a pointer to the first element, in this case equivalent to char (*array)[15]). If you do sizeof array instead the function, you get the size of a pointer (4 or 8 etc). If you do sizeof *array you just get the size of one dimension, 15.
A simple way to fix it:
#include <stdio.h>
#include <string.h>
void fillseats (size_t x, size_t y, char array[x][y])
{
memset(array, '.', sizeof(char[x][y]));
}
void printseatingplan (size_t x, size_t y, char array[x][y])
{
for (size_t i = 0; i < x; i++)
{
for(size_t j = 0; j < y; j++)
{
printf("%c",array[i][j]);
}
printf("\n");
}
}
int main (void)
{
char seatingplan[15][15];
fillseats(15, 15, seatingplan);
printseatingplan(15, 15, seatingplan);
}
The size of array is bound to its type. The problem is that the parameters of array type decay to pointers. To prevent it, you can pass a pointer to an array. The pointer don't decay thus the essential part of the array type prevails.
void printseatingplan(char (*array)[15][15])
{
for (int k = 0; k < 15; ++k)
{
for(int j = 0; j < 15; ++j)
{
printf("%c", (*array)[k][j]);
}
printf("\n");
}
}
void fillseats(char (*array)[15][15])
{
memset(*array,'.',sizeof *array);
}
int main (void)
{
char seatingplan[15][15];
fillseats(&seatingplan);
printseatingplan(&seatingplan);
}

expected ‘int **’ but argument is of type ‘int (*)[3]’

I just started to tinker with pointers in multidimensional arrays and was trying to pass and array into a void function. The compilator just threw an error. I need the array to be passed exactly as a pointer to maybe change it then by reference.
#include <stdio.h>
#include <stdlib.h>
void Func(int** matrix, int sizeFirst, int sizeSecond)
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d\n", matrix[i][j]);
}
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
int sizeMain = sizeof(array)/sizeof(array[0]);
int sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(array, sizeMain, sizeInner);
return 0;
}
2D array is not pointer to pointer. Your code is invalid as Func does not know how many columns every row has. Also, use the correct type for sizes & indexes
void Func(size_t sizeFirst, size_t sizeSecond, int (*matrix)[sizeSecond])
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
size_t sizeMain = sizeof(array)/sizeof(array[0]);
size_t sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(sizeMain, sizeInner, array);
return 0;
}
https://godbolt.org/z/Ejfrdd3nK
With pointers to VLAs, you can preserve all of the dimensions in the type of the argument and then let C do the multidimensional scaling for you.
In older versions of C you need to calculate the spot manually, remembering that
the first dimension from the right moves by 1 (scaled by sizeof(type), which C does for you), the second by first dimension from the right,
the third by first dimension from the right multiplied by second dimension from the right and so on.
It's sort of like digits in numbers (units, tens, hundreds, ...) except that the next scaling is the previous scaling multiplied by the previous dimension rather than by a constant radix.
(You could let C convert groups of decimal digits to decimal numbers by letting it subtract some &decdigits[a][b][c] and &decdigits[0][0][0] where decdigits is some decdigits[10][10][10], i.e.:
char decdigits[10][10][10]; printf("%d\n", (int)(&decdigits[1][2][3] - &decdigits[0][0][0])) /*prints 123*/;)
#include <stdio.h>
void Func( int sizeFirst, int sizeSecond, int (*matrix)[sizeFirst][sizeSecond])
{
for (int i = 0; i < sizeof((*matrix))/sizeof((*matrix)[0]) ; i++)
{
for (int j = 0; j < sizeof((*matrix)[0])/sizeof((*matrix)[0][0]) ; j++)
{
printf("%d ", (*matrix)[i][j]);
}
puts("");
}
}
void Func_89( int sizeFirst, int sizeSecond, int *matrix)
{
for (int i = 0; i < sizeFirst; i++)
{
for (int j = 0; j < sizeSecond; j++)
{
printf("%d ", matrix[i*sizeSecond + j]);
}
puts("");
}
}
int main()
{
int array[2][3] = {
{5,8,2},
{1,3,6}
};
int sizeMain = sizeof(array)/sizeof(array[0]);
int sizeInner = sizeof(array[0])/sizeof(array[0][0]);
Func(sizeMain, sizeInner,&array );
puts("===");
Func_89(sizeMain, sizeInner,&array[0][0] );
//char decdigits[10][10][10]; printf("%d\n", (int)(&decdigits[1][2][3] - &decdigits[0][0][0])); //123
return 0;
}
First of you have to understand what int ** represent, it represents pointer to integer pointer, here's an example:
int a = 10;
int *p = &a; // 'p' points to 'a`
int **pp = &p; // 'pp' points to 'p' (pointer to integer)
So because of this, you can't use int ** for an integer array. Now that's out of the way, let's see what can you do instead (solution)
You can simply add a pointer to an integer array in a function definition like this
void Func(int *matrix[], int rows, int cols)
Or you can simply do
void Func(int matrix[rows][cols])
Note: Array of strings or 2D character array (char array[][]) can be represented as char**

C: Heap block at ### modified at ### past requested size of ###

So I'm storing a 2D dynamic Array into a matrix struct:
struct Matrix {
int ncol;
int nrow;
double **mat;
};
typedef struct Matrix Matrix;
I then have a function that takes the contents from a 2D array and stores it into the matrix:
// Initializes matrix mat whose values are the passed in 2D array
// Made Matrix **mat a double pointer so that I can initialize the Matrix *pointer from Main
void matrix_initializeFromArray(Matrix **mat, int nrow, int ncol, double array[][ncol]) {
(*mat) = (Matrix*) malloc(sizeof(Matrix*));
(*mat)->mat = (double**) malloc(nrow*sizeof(double*));
for(int i = 0; i < nrow; i++) {
(*mat)->mat[i] = (double*) malloc(ncol*sizeof(double*));
for(int j = 0; j < ncol; j++) { // intialize all values to array values
(*mat)->mat[i][j] = array[i][j];
}
}
(*mat)->ncol = ncol;
(*mat)->nrow = nrow;
}
Where this is the destructor for the matrix:
// Destructor
void matrix_destructor(Matrix **mat) {
for(int i = 0; i < (*mat)->nrow; i++) {
free((*mat)->mat[i]);
}
free((*mat)->mat);
free(*mat);
}
A small example of this is the following:
void main() {
Matrix *temp;
double array[1][1];
array[0][0] = 34;
matrix_initializeFromArray(&temp, 1, 1, array);
matrix_print(temp);
matrix_destructor(&temp);
}
This code executes normally on gdb and valgrind in my Linux Ubuntu but for some reason it creates this error while I run it on Windows.
warning: HEAP[a.exe]:
warning: Heap block at 00B51710 modified at 00B5171C past requested size of 4
I ran through the gdb on Windows and it occurs at this line in the destructor on the first loop: free((*mat)->mat[i]);
Any Help?
I have simplified your code, matrix_print is missing
The issue was with the malloc
when you allocate something you get a pointer to the memory, for example
malloc(sizeof(double)); returns a pointer to a memory area that can store a double so a double *
malloc(sizeof(double*)); returns a pointer to a memory are that can store a pointer to a double, so a double **`
#include <stdio.h>
#include <stdlib.h>
struct Matrix {
int ncol;
int nrow;
double **mat;
};
typedef struct Matrix Matrix;
void matrix_initializeFromArray(Matrix *mat, int nrow, int ncol, double array[][ncol]) {
mat->ncol = ncol;
mat->nrow = nrow;
mat->mat = malloc(nrow * sizeof(double*));
for(int i = 0; i < nrow; i++) {
mat->mat[i] = malloc(ncol*sizeof(double));
for(int j = 0; j < ncol; j++) { // intialize all values to array values
mat->mat[i][j] = array[i][j];
}
}
}
void matrix_wipe(Matrix *mat) {
for(int i = 0; i < mat->nrow; i++) {
free(mat->mat[i]);
}
free(mat->mat);
}
int main(void) {
Matrix temp;
double array[1][1];
array[0][0] = 34;
matrix_initializeFromArray(&temp, 1, 1, array);
matrix_wipe(&temp);
return 0;
}

2D arrays using arrays of pointers or pointers to pointers in C?

I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!

C typedef: pointer to struct

For my personal entertainment I am learning C. I am trying to write a matrix calculation header. I have a function to show the matrix, rmat_show(rmatrix *r), which should printf the entire matrix. However, it seems that my data type rmatrix is not passed well to this function.
rmat.h:
// Matrix struct, m x n matrix. Pointer *value points to the contents.
struct srmatrix {
int m,n;
float *value;
};
typedef struct srmatrix rmatrix;
// Show the matrix
void rmat_show(rmatrix* r) {
int i, j;
printf("\nshow\n");
printf("[%dx%d]\n",r->m,r->n);
for (i = 0; i < r->m; i++) {
for (j = 0; j < r->m; j++) {
printf("%d\t",value[(j-1)*r->m+i-1]);
}
printf("\n");
}
}
And I have this as main file:
#include "rmat.h"
int main(int argc, char **argv){
float val[] = {0.1};
rmatrix *r = malloc(sizeof(rmatrix));
r->n = 1;
r->m = 1;
r->value = val;
rmat_show(r);
return 0;
}
After rmat_show I attempt to kill te matrix with another function. It yields the same error, which is: 'incompatible type for argument 1 of 'rmat_show' expected 'rmatrix' but argument was of type 'struct rmatrix *''. I have tried searching 'pointer to typedef' and similar terms, without result. I believe the typedef declaration is not carried over to the function defenition. I use msys and mingw on windows 7.
Thanks for the help.
Edit: added the typedef line I miscopied.
Seems you are using the same loop variable twice
for (i = 0; i < r->m; i++) {
for (i = 0; i < r->m; i++)
you probably meant
for (i = 0; i < r->m; i++) {
for (j = 0; j < r->n; j++)
EDIT:
you may want to use the right name of the struct as well
struct srmatrix
not
rmatrix *r = malloc(sizeof(rmatrix));
but
struct srmatrix *r = malloc(sizeof(struct srmatrix));
whether you include struct or not depends on your compiler version C/C++
This
struct srmatrix {
int m,n;
float *value;
};
...
void rmat_show(rmatrix* r)
{
...
for (i = 0; i < r->m; i++)
{
for (i = 0; i < r->m; i++)
{
printf("%d\t", value[(n-1)*r->m+m-1]);
}
printf("\n");
}
...
should be this
rmat.h:
#ifndef RMAT_H
#define RMAT_H
typedef struct rmatrix_s {
size_t m, n; /* There is no need to define dimension as signed. */
float * value;
} rmatrix_t;
void rmat_show(rmatrix_t * r);
#endif
rmat.c:
...
#include "rmat.h"
void rmat_show(rmatrix_t * r)
{
...
for (size_t j = 0; j < r->n; j++)
{
for (size_t i = 0; i < r->m; i++)
{
printf("%d\t", value[j*r->m + i]);
}
printf("\n");
}
The main would then have:
...
#include "rmat.h"
int main(int argc, char **argv)
{
...
rmatrix_t * r = malloc(sizeof(*r));
...
To compile this do:
gcc -g -Wall -Wextra -o main main.c rmat.c

Resources