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
Related
I have to make 2 programs. One that write a matrix on a shared memory and one that must read and order this matrix.
I created a shared structure that is the var that I will put on the shared memory. But I don't know how to read and store on another var.
My shared structure:
#define QUANTIDADE 100
#define TAMANHO 1000
struct shared_use_st {
int written_by_you;
int num_processos_executando;
int arrays[QUANTIDADE][TAMANHO];
};
How I create my matrix on the writer code:
int i, j;
for (j = 0; j < QUANTIDADE; j++) {
for (i = 0; i < TAMANHO; i++) {
shared_stuff->arrays[j][i] = rand();
}
}
How I want to read from the memory:
int my_arrays[QUANTIDADE][TAMANHO];
int main() {
[...]
my_arrays = shared_stuff->arrays; //Error
[...]
}
You can't assign to an array directly. You'll need to copy each element:
int i, j;
for (j = 0; j < QUANTIDADE; j++){
for (i = 0; i < TAMANHO; i++) {
my_arrays[j][i] = shared_stuff->arrays[j][i];
}
}
Or use memcpy:
memcpy(my_arrays, shared_stuff->arrays, sizeof(my_arrays));
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]);
..
}
I want to reshape an array of length L to one of MxN, however rather than create new memory by copying the elements over in for loops I'd like to do some pointer casting to allow me to access the array with double subscripting (array[X][Y]) .
I've googled around for ages and couldn't find anything helpful.
Any help would really be appreciated.
EDIT: The array of interest is on the heap not stack.
Pointer casting doesn't seem like a good idea here. But if the number of columns is known before run-time, one option I often encounter is to simply define a macro e.g.
#define arrayName(i,j) arrayName[((i)*N) + (j)]
Or
#define ELEMENT(arrayName, i,j) (arrayName)[((i)*N) + (j)]
if you want it to be more flexible.
unions are your friends:
#include <stdio.h>
#define M 5
#define N 4
typedef union {
int a1[M * N];
int a2[M][N];
} U;
int main()
{
U u;
int i, j;
for (i = 0; i < M * N; ++i)
{
u.a1[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", u.a2[i][j]);
}
printf("\n");
}
return 0;
}
typedefs are your friends:
#include <stdio.h>
#include <stdlib.h>
#define M 5
#define N 4
typedef int Array1D[M * N];
typedef int Array2D[M][N];
int main()
{
Array1D *a1 = malloc(sizeof(*a1));
Array2D *a2 = (Array2D *)a1;
int i, j;
for (i = 0; i < M * N; ++i)
{
(*a1)[i] = i;
}
for (i = 0; i < M; ++i)
{
for (j = 0; j < N; ++j)
{
printf("%8d", (*a2)[i][j]);
}
printf("\n");
}
free(a1);
return 0;
}
Note: above code has now been updated to use heap allocation so as not to break strict aliasing rules.
By the way if you want it super dynamic (as in no sizes are known at compile-time) you can do this by not copying all the values but by creating an index for the 2nd dimension like so:
#include <stdio.h>
#include <stdlib.h>
const int FULL = 100;
const int X = 10;
const int Y = 10;
int *dim1;
int **nested;
int main(void) {
dim1 = malloc(sizeof(int)*FULL);
nested = malloc(sizeof(int*)*X);
for(int i=0; i<X;i++)
{
nested[i] = &dim1[Y*i];
}
dim1[15] = 42;
printf("nested[1][5]: %d",nested[1][5]);
free(nested);
free(dim1);
return 0;
}
Can someone wiser than I please explain to me why the following code segment faults? There is no problem allocating the memory by reference, but as soon as I try to assign anything or free by reference, segfault occurs.
I'm sure I'm missing some fundamental concept about pointers and passing by reference, hopefully some light can be shed.
#include <stdlib.h>
#include <stdio.h>
void allocateMatrix(float ***);
void fillMatrix(float ***);
void freeMatrix(float **);
int main() {
float **matrix;
allocateMatrix(&matrix); // this function calls and returns OK
fillMatrix(&matrix); // this function will segfault
freeMatrix(matrix); // this function will segfault
exit(0);
}
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
void fillMatrix(float ***m) {
int i,j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(*m)[i][j] = 1.0; // SEGFAULT
}
}
return;
}
void freeMatrix(float **m) {
int i;
for (i = 0; i < 2; i++) {
free(m[i]); // SEGFAULT
}
free(m);
return;
}
One set of problems is here:
void allocateMatrix(float ***m) {
int i;
m = malloc(2*sizeof(float*));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return;
}
You need to assign to *m to get the information back to the calling code, and also you will need to allocate to (*m)[i] in the loop.
void allocateMatrix(float ***m)
{
*m = malloc(2*sizeof(float*));
for (int i = 0; i < 2; i++)
(*m)[i] = malloc(2*sizeof(float));
}
There's at least a chance that the other functions are OK. The fillMatrix() is written and invoked correctly, though it could be simplified by losing the third * from the pointer:
void fillMatrix(float **m)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
m[i][j] = 1.0;
}
}
It might be advisable to pass the triple-pointer to freeMatrix() so that you can zero the pointer in the calling function:
void freeMatrix(float ***m)
{
for (int i = 0; i < 2; i++)
free((*m)[i]);
free(*m);
*m = 0;
}
Calling then becomes:
allocateMatrix(&matrix);
fillMatrix(matrix);
freeMatrix(&matrix);
Good use of indirection. Just try to be consistent with format. It improves readability and reduces errors. e.g.
function calls:
allocateMatrix &matrix
fillMatrix &matrix
freeMatrix &matrix
declarations
void allocateMatrix float ***m
void fillMatrix float ***m
void freeMatrix float ***m
handling
(*m)[i] = malloc(2 * sizeof(float))
(*m)[i][j] = 1.0
free (*m)[i]
Returning of pointer from your function is probably the better way to allocate memory:
float **allocateMatrix() {
int i;
float **m;
m = malloc(2*sizeof(float *));
for (i = 0; i < 2; i++) {
m[i] = malloc(2*sizeof(float));
}
return m;
}
int main() {
float **m;
m = allocateMatrix();
/* do other things
fillMatrix(matrix);
freeMatrix(&matrix);
*/
}
I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format.
I have run into a strange memory allocation issue that no one seems to have seen before. My code is:
yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;
yale* yale = (struct y*)calloc(1, sizeof(yale));
int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));
int* JA = (int*)calloc(matrix_elements, sizeof(int));
printf("%d elements\n",matrix_elements);
yale->A = A; // Value
yale->IA = IA; // Row (X)
yale->JA = JA; // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
list* tmp_list = input->first;
for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
printf("Input Value: %d \n",tmp_list->point.value);
A[i] = tmp_list->point.value;
// Initialise the first row
if(i == 0) IA[0] = tmp_list->point.x;
else{
// Add a new row index
if(tmp_y != tmp_list->point.x){
j++;
IA[j] = i;
tmp_y = tmp_list->point.x;
}
}
JA[i] = tmp_list->point.y;
tmp_list = tmp_list->next;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->JA[i]);
return yale;
}
And here is the struct for yale:
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
But the program segfaults at the first relevant printf on the first iteration of the loop.
printf("%d,",yale->A[i]);
I'm positive:
matrix_elements is an integer (9 in my test case)
matrix_rows is an integer
A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine).
Directly callocing the array to the struct pointers doesn't affect the result.
Mallocing, callocing, not typecasting, all no effect.
Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays
I suggest you run your code under Valgrind. This should report the buffer overflow error. (A buffer overflow is where you write past the end of an array).
I also recommend you write some unit tests for your code. They can be very helpful detecting bugs. In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. Check that the values you get out are what you expect.
To get it compiled, I need to prepend this to the snippet:
#include <stdlib.h>
#include <stdio.h>
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
typedef struct list {
struct list *next;
struct point { int x,y,value; } point;
} list;
typedef struct matrix_list {
int elements;
int m;
int n;
struct list *first;
int *point;
} matrix_list;
UPDATE: I transformed the program into something more readable (IMHO). I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct y {
unsigned int n;
unsigned int m;
unsigned int elements;
unsigned int *IA;
unsigned int *JA;
int *A;
} ;
struct list {
struct list *next;
struct point { unsigned int x,y; int value; } point;
} ;
struct matrix_list {
unsigned int elements;
unsigned int m;
unsigned int n;
struct list *first;
} ;
struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;
struct y *yale ;
struct list *tmp_list ;
yale = calloc(1, sizeof *yale);
assert (yale != NULL);
printf("%u elements\n",matrix_elements);
yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
// Initialise the first row, set start condition
// FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
printf("Input Value: %d \n",tmp_list->point.value);
yale->A[ii] = tmp_list->point.value;
// Add a new row index
if(tmp_y != tmp_list->point.x){
jj++;
yale->IA[jj] = ii;
tmp_y = tmp_list->point.x;
}
yale->JA[ii] = tmp_list->point.y;
if (++ii >= matrix_elements ) break;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%u,",yale->JA[i]);
return yale;
}
Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. Also: all the indices are unsigned (as they should be)