I want to use a struct to contain some data and passing them between different functions in my program,this struct has to contain a dynamic 2D array (i need a matrix) the dimensions change depending on program arguments.
So this is my struct :
struct mystruct {
int **my2darray;
}
I have a function that read numbers from a file and has to assign each of them to a cell of the struct array.
I tried doing this :
FILE *fp = fopen(filename, "r");
int rows;
int columns;
struct mystruct *result = malloc(sizeof(struct mystruct));
result->my2darray = malloc(sizeof(int)*rows);
int tmp[rows][columns];
for(int i = 0;i<rows;i++) {
for(int j = 0;j<columns;j++) {
fscanf(fp, "%d", &tmp[i][j]);
}
result->my2darray[i]=malloc(sizeof(int)*columns);
memcpy(result->my2darray[i],tmp[i],sizeof(tmp[i]));
}
But this is giving me a strange result : all the rows are correctly stored except for the first.
(I'm sure that the problem is not in the scanning of file).
While if i change the fourth line of code in this :
result->my2darray = malloc(sizeof(int)*(rows+1));
it works fine.
Now my question is why this happens?
Here's an answer using some "new" features of the language: flexible array members and pointers to VLA.
First of all, please check Correctly allocating multi-dimensional arrays. You'll want a 2D array, not some look-up table.
To allocate such a true 2D array, you can utilize flexible array members:
typedef struct
{
size_t x;
size_t y;
int flex[];
} array2d_t;
It will be allocated as a true array, although "mangled" into a single dimension:
size_t x = 2;
size_t y = 3;
array2d_t* arr2d = malloc( sizeof *arr2d + sizeof(int[x][y]) );
Because the problem with flexible array members is that they can neither be VLA nor 2-dimensional. And although casting it to another integer array type is safe (in regards of aliasing and alignment), the syntax is quite evil:
int(*ptr)[y] = (int(*)[y]) arr2d->flex; // bleh!
It would be possible hide all this evil syntax behind a macro:
#define get_array(arr2d) \
_Generic( (arr2d), \
array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )
Read as: if arr2d is a of type array2d_t* then access that pointer to get the flex member, then cast it to an array pointer of appropriate type.
Full example:
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
size_t x;
size_t y;
int flex[];
} array2d_t;
#define get_array(arr2d) \
_Generic( (arr2d), \
array2d_t*: (int(*)[(arr2d)->y])(arr2d)->flex )
int main (void)
{
size_t x = 2;
size_t y = 3;
array2d_t* arr = malloc( sizeof *arr + sizeof(int[x][y]) );
arr->x = x;
arr->y = y;
for(size_t i=0; i<arr->x; i++)
{
for(size_t j=0; j<arr->y; j++)
{
get_array(arr)[i][j] = i+j;
printf("%d ", get_array(arr)[i][j]);
}
printf("\n");
}
free(arr);
return 0;
}
Advantages over pointer-to-pointer:
An actual 2D array that can be allocated/freed with a single function call, and can be passed to functions like memcpy.
For example if you have two array2d_t* pointing at allocated memory, you can copy all the contents with a single memcpy call, without needing to access individual members.
No extra clutter in the struct, just the array.
No cache misses upon array access due to the memory being segmented all over the heap.
The code above never sets rows and columns, so the code has undefined behavior from reading those values.
Assuming you set those values properly, this isn't allocating the proper amount of memory:
result->my2darray = malloc(sizeof(int)*rows);
You're actually allocating space for an array of int instead of an array of int *. If the latter is larger (and it most likely is) then you haven't allocated enough space for the array and you again invoke undefined behavior by writing past the end of allocated memory.
You can allocate the proper amount of space like this:
result->my2darray = malloc(sizeof(int *)*rows);
Or even better, as this doesn't depend on the actual type:
result->my2darray = malloc(sizeof(*result->my2darray)*rows);
Also, there's no need to create a temporary array to read values into. Just read them directly into my2darray:
for(int i = 0;i<rows;i++) {
result->my2darray[i]=malloc(sizeof(int)*columns);
for(int j = 0;j<columns;j++) {
fscanf(fp, "%d", &result->my2darray[i][j]);
}
}
In your provided code example, the variables rows and columns have not been initialized before use, so they can contain anything, but are likely to be equal to 0. Either way, as written, the results will always be unpredictable.
When a 2D array is needed in C, it is useful to encapsulate the memory allocation, and freeing of memory into functions to simplify the task, and improve readability. For example, in your code the following line will create an array of 5 pointers, each pointing to 20 int storage locations: (creating 100 index addressable int locations.)
int main(void)
{
struct mystruct result = {0};
result.my2darray = Create2D(5, 20);
if(result.my2darray)
{
// use result.my2darray
result.my2darray[0][3] = 20;// for simple example, but more likely in a read loop
// then free result.my2darray
free2D(result.my2darray, 5);
}
return 0;
}
Using the following two functions:
int ** Create2D(int c, int r)
{
int **arr;
int y;
arr = calloc(c, sizeof(int *)); //create c pointers (columns)
for(y=0;y<c;y++)
{
arr[y] = calloc(r, sizeof(int)); //create r int locations for each pointer (rows)
}
return arr;
}
void free2D(int **arr, int c)
{
int i;
if(!arr) return;
for(i=0;i<c;i++)
{
if(arr[i])
{
free(arr[i]);
arr[i] = NULL;
}
}
free(arr);
arr = NULL;
}
Keep in mind that what you have created using this technique is actually 5 different pointer locations each pointing to a set of 20 int locations. This is what facilitates the use of array like indexing, i.e. we can say result.my2darray[1][3] represents the second column, forth row element of a 5X20 array, when it is not really an array at all.
int some_array[5][20] = {0};//init all elements to zero
Is what is commonly referred to in C an int array, also allowing access to each element via indexing. In actuality (Even though commonly referred to as an array.) it is not an array. The location of elements in this variable are stored in one contiguous location in memory.
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0... (~ 82 more)
But C maintains the locations such that they are all indexable as an 2D array.
Related
As said in title, I have a question regarding using * twice, like in the main function of the following code. it DOES run, but I don't understand why using ** is right here. What i want is an array of SPPoints , sized n, where parr is the base adress. Why is ** right and * wrong in this case? thanks.
SPPoint code:
struct sp_point_t
{
double* data;
int dim;
int index;
};
SPPoint* spPointCreate(double* data, int dim, int index)
{
if (data == NULL || dim <= 0 || index < 0)
{
return NULL;
}
SPPoint* point = malloc(sizeof(*point));
if (point == NULL)
{
return NULL;
}
point->data = (double*)malloc(dim * sizeof(*data));
for (int i = 0; i < dim; i++)
{
point->data[i] = data[i];
}
point->dim = dim;
point->index = index;
return point;
}
And this is the main function:
int main()
{
int n, d, k;
scanf("%d %d %d", &n, &d, &k);
double* darr = malloc(d * sizeof(double));
if (darr == NULL)
{
return 0;
}
SPPoint** parr = malloc(n * sizeof(SPPoint*));
if (parr == NULL)
{
return 0;
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < d; j++)
{
scanf(" %lf", &darr[j]);
}
parr[i] = spPointCreate(darr, d, i);
}
}
When using a dynamically-allocated array, it's usually "handled" by having a pointer to the first element of the array, and also having some method of knowing the length, such as explicitly storing the length, or having an end sentinel.
So for a dynamically allocated array of SPPoint * as you have in your code, a pointer to the first one of those has type SPPoint * *
Your existing code creates an array of SPPoint *, i.e. an array of pointers. Each of those pointers points to one dynamically-allocated instance of SPPoint, i.e. you have separate allocations for each entry.
This is viable but you indicate that you instead wanted an array of SPPoint, in which case a pointer to the first element has type SPPoint *.
In order to have such an array, it is a single memory allocation. So you will need to redesign your spPointCreate function. Currently that allocates memory for and initializes only a single SPPoint. Instead you want to separate the allocation from the initialization, since you only need one allocation but you need multiple initializations. Your program logic will read something like:
Allocate one block of memory big enough for n SPPoints
Initialize each SPPoint inside the allocated space
If you have tried this but got stuck then post a new question showing your code and explaining where you got stuck.
An array can behave similarly to a pointer. For instance, int a [] is very similar to int* a. Each function in SPPoint returns a pointer to a SPPoint struct. An array of pointers to SPPoint can be written as a pointer to a pointer to SPPoint. With the malloc command, you are designating a certain amount of memory (enough to hold n pointers to SPPoint) for storage of pointers to SPPoint structs.
Not all pointers are arrays, however. SPPoint** parr is acting as an array holding pointers to single structs of type SPPoint.
Arrays can behave differently from pointers, especially when used for strings.
The reason why it is advantageous to use pointers to SPPoint (as you are now) is that you can view or modify a single element without having to copy the entire struct.
I have a function which creates an array, of say, size 5.
Is it possible for the function to accept a pointer (or maybe it needs a pointer to a pointer?) and then point said pointer at an array, so that when the callee then looks at the pointer, it can see all values of the array.
Something along the lines of this (except this will not work):
#define LENGTH 5
void assignArray(int *pointer)
{
int arr[LENGTH] = {0,1,2,3,4};
// Point the pointer at the array, without manually copying each element
pointer = arr;
}
void main()
{
int *pointer;
pointer = malloc(sizeof(int) * LENGTH);
assignArray(pointer);
int i;
for (i = 0 ; i < LENGTH ; i++) printf("%d\n", pointer[i]);
}
C assign array without element by element copy
In C, arrays (compile-time allocated) cannot be assigned. You need to copy the elements from one array to another.
To avoid element-by-element copy, you can copy the whole array all at a time using library function.
I'm not very sure what you want to ask here, but it seems, you need to do memcpy() to achieve your goal.
If you have a secondary array arr to copy from, you can write
memcpy( pointer, arr, ( (sizeof arr[0]) * LENGTH ));
The code to do what you are describing might look like:
#define LENGTH 5
void assignArray(int **pp)
{
static int arr[LENGTH] = {0,1,2,3,4};
// Point the pointer at the array, without manually copying each element
*pp = arr;
}
int main()
{
int *pointer;
assignArray(&pointer);
for (int i = 0 ; i < LENGTH ; i++)
printf("%d\n", pointer[i]);
}
Note that one does not simply point *pp at a non-static local variable arr. That is because int arr[] = .... would go out of scope when assignArray returns.
If you want each call to assignArray to "return" a different array then of course you will have to allocate space and use memcpy each time you want to make a copy of the original array.
int arr[LENGTH] = {0,1,2,3,4}; will be stack allocated, so attempting to return the pointer to any of its elements will give you undefined behaviour as the whole thing will be out of scope when the function returns.
If you want to change what a pointer is pointing to then use 2 levels of indirection ** (i.e. pass a pointer to a pointer). You'll need to allocate the array arr on the heap using malloc or something similar.
As you are trying to do it, it is not possible due to the fact that your local arr is saved to the stack and is cleaned up after the function assignArry finished. As already mentioned you need to memcpy.
This answer will have two parts:
As mentioned in other answers, this is now how you're supposed to do it. A common construct in similar code is:
void assignArray(int *dest, size_t size)
{
int i;
// initialize with some data
for (i=0; i<size; i++)
dest[i] = i;
}
This way you're not wasting space and time with an intermediate buffer.
Second part of this answer is about wrapping arrays in a struct. It's a silly trick, that in a way achieves exactly what you asked, and also something that you probably don't want because of extra data copying.
Example code:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 5
struct foo { int arr[LENGTH]; };
struct foo assignArray()
{
struct foo bar = { .arr = {0,1,2,3,4} };
/* return the array wrapper in struct on stack */
return bar;
}
int main()
{
struct foo *pointer;
pointer = malloc(sizeof(*pointer));
*pointer = assignArray(); /* this will copy the data, not adjust pointer location */
int i;
for (i = 0 ; i < LENGTH ; i++) printf("%d\n", pointer->arr[i]);
return 0;
}
Hello I am new to C and I need someone to explain concepts to me. I am a JAVA programmer and I am trying to write a program in C. My current issue is trying to initialize an array with an unknown number. I know in C an array has to be initialized with a number instead of a variable like you can in Java. My question is if I can do this in Java:
int i = 0;
char array [i];
void f(){
\\some code
i++;
}
How can I do this in C? I'm trying to fill an array with certain strings that I get from a file. I don't know how many I will be getting from the file however. I have tried reading about malloc but in one tutorial it says:
int *pointer;
pointer=malloc(2*sizeof(int));
is equivalent to
int array[2];
But I'm looking for a way to do this while increment the array.
First to mention, malloc() and family is used for dynamic (runtime) memory allocation whereas int arr[2] usually denotes compile time memory allocation. They are not exactly equivalent.
However, if you want to resize the allocated memory on-the-fly, you're on right track. What you need to do next is to use realloc() to re-size the previously allocated memory location.
You can read the man page for more details.
Also, while using dynamic memory in C, you need to keep in mid that there is no garbage collector in C. You need to free() up every bit of memory allocated by you.
I know in C an array has to be initialized with a number instead of a variable like you can in Java
In C99 and beyond, variable initiated arrays are available.
My current issue is trying to initialize an array with an unknown number.
and:
But I'm looking for a way to do this while increment the array.
If you have an unknown number of elements at run-time, you can write a function to create (and free) memory, passing the relevant arguments as you need them. Here is an example of a function to create (and free) a 2 dimensional array of ints:
int ** Create2Dint(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = calloc(space, sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
void free2DInt(int **arr, int cols)
{
int i;
for(i=0;i<cols; i++)
if(arr[i]) free(arr[i]);
free(arr);
}
If, during execution, you need to change the allocation of memory (change the size of the array) you can use realloc(), implemented here in similar fashion:
int ** Realloc2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = realloc(arr, space*sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
Usage example:
(execute with two integer command line arguments, both > 0)
int main(int argc, char *argv[])
{
int **array = {0};
int cols, rows;
cols = atoi(argv[1]);
rows = atoi(argv[2]);
array = Create2Dint(array, cols, rows);
//Do stuff here to use array
//Memory requirements change during runtime:
cols += 20;
rows += 50;
array = Realloc2D(array, cols, rows);
//use array again...
//When you are finished with the memory, free it:
free2DInt(array, cols);
return 0;
}
I am trying to dynamically allocate a 2D array, put some values, and print output. However it seems that I am making mistake in getting input to program in atoi() function.
Basically when we assign a static 2D array, we declare it as say int a [3][3]. So 3*3 units if int, that much memory gets allocated. Is same thing holds for allocating dynamic array as well?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
int main(int arg,char* argv)
{
int rows = atoi(argv[1]);
int col = atoi(argv[2]);
int rows =3;
int col=3;
int i,j;
int (*arr)[col] = malloc(sizeof (*arr)*rows);
int *ptr = &(arr[0][0]);
int ct=1;
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
arr[i][j]=ct;
ct++;
}
}
printf("printing array \n");
for (i=0;i<rows;i++)
{
for(j=0;j<col;j++)
{
printf("%d \t",arr[i][j]);
}
printf("\n");
}
free(arr);
return (0);
}
Program crashes in runtime. Can someone comment?
The first issue I see is this line:
int (*arr)[rows][col] = malloc(sizeof (*arr) * rows);
This is not problematic at all because you are in fact allocating more memory than you need. This would suffice:
int (*arr)[rows][col] = malloc(sizeof (*arr));
sizeof *arr is enough because *arr is of type int [rows][cols]; the memory you want is exactly the size of that array. The sizeof operator, when applied to arrays, gives you the count for the whole array.
The main problem with your code, however, is how you use arr. You are indexing it with arr[i][j], but instead, you should be using (*arr)[i][j], because arr is not an array, it's a pointer to an array. You need to dereference it before any further indexing - as simple as that. arr[i][j] is equivalent to *(*(arr+i)+j). Note that i should be an offset into *arr, not an offset on arr. That's why you need to dereference arr before indexing.
Since you're already using variable-length arrays, you may take advantage of that:
int (*arr)[col] = malloc(sizeof *arr * rows);
This way you can simply access elements with the usual syntax arr[i][j] without worrying about pointers and dereferences, pointer arithmetic will do all the work for you.
Also since indexes start from 0 your tests should look like i < rows and j < col.
And you have some minor errors for the wrong main declaration and the second printf.
I am given the following structures to create my code with:
struct Mtrx {
unsigned double h;
struct MtrxRows** mtrxrows;
}
struct MtrxRows {
unsigned double w;
double* row;
}
I am trying to create a method called mtrxCreate that takes in parameters height and width and this is what I have below:
Mtrx* mtrxCreate(unsigned double height, unsigned double width){
Mtrx* mtrx_ptr = malloc(sizeof(double)*height);
int i;
mtrx_ptr->mtrxrows = malloc(sizeof(double)*height);
for(i = 0; i < height; ++i){
mtrx_ptr->mtrxrows[i]->row = malloc(sizeof(double) * width);
mtrx_ptr->mtrxrows[i]->w = width;
}
mtrx_ptr->h = height;
return mtrx_ptr;
}
The GCC compiler is telling me that I have a segmentation fault so I believe I did not allocate the memory correctly. I am not sure what memory I am still needing to allocating and if I allocated the current amount to the parts of the matrix above, any help is appreciated!
You aren't allocating the right amount of memory for certain things. First of all, the Mtrx structure itself:
Mtrx* mtrx_ptr = malloc(sizeof(double)*height);
Should be:
Mtrx* mtrx_ptr = malloc(sizeof(struct Mtrx));
Next, I'm not sure why your mtrxrows field is a double pointer. I think it should be a single pointer, a one-dimensional array of rows (where each row has some number of elements in it, as well). If you change it to a single pointer, you would allocate the rows as such:
mtrx_ptr->mtrxrows = malloc(sizeof(struct MtrxRows)*height);
Edit: Sorry I keep noticing things in this sample, so I've tweaked the answer a bit.
Wow. I don't exactly know where to start with cleaning that up, so I'm going to try to start from scratch.
From your code, it seems like you want all rows and all columns to be the same size - that is, no two rows will have different sizes. If this is wrong, let me know, but it's much harder to do.
Now then, first let's define a struct to hold the number of rows, the number of columns, and the array data itself.
struct Matrix {
size_t width;
size_t height;
double **data;
};
There are different ways to do store the data, but we can look at those later.
size_t is an unsigned integer (not floating point - there are no unsigned floating point types) type defined in stddef.h (among other places) to be large enough to store any valid object size or array index. Since we need to store array sizes, it's exactly what we need to store the height and width of our matrix.
double **data is a pointer to a pointer to a double, which is (in this case) a complex way to say a two-dimensional array of doubles that we allocate at runtime with malloc.
Let's begin defining a function. All these lines of code go together, but I'm splitting them up to make sure you understand all the different parts.
struct Matrix *make_Matrix(size_t width, size_t height, double fill)
Notice that you have to say struct Matrix, not just Matrix. If you want to drop the struct you'd have to use a typedef, but it's not that important IMHO. The fill parameter will allow the user to specify a default value for all the elements of the matrix.
{
struct Matrix *m = malloc(sizeof(struct Matrix));
if(m == NULL) return NULL;
This line allocates enough memory to store a struct Matrix. If it couldn't allocate any memory, we return NULL.
m->height = height;
m->width = width;
m->data = malloc(sizeof(double *) * height);
if(m->data == NULL)
{
free(m);
return NULL;
}
All that should make sense. Since m->data is a double **, it points to double *s, so we have to allocate a number of double *-sized objects to store in it. If we want it to be our array height, we allocate height number of double *s, that is, sizeof(double *) * height. Remember: if your pointer is a T *, you need to allocate T-sized objects.
If the allocation fails, we can't just return NULL - that would leak memory! We have to free our previously allocated but incomplete matrix before we return NULL.
for(size_t i = 0; i < height; i++)
{
m->data[i] = malloc(sizeof(double) * width);
if(m->data[i] == NULL)
{
for(size_t j = 0; j < i; j++) free(m->data[j]);
free(m->data);
free(m);
return 0;
}
Now we're looping over every column and allocating a row. Notice we allocate sizeof(double) * width space - since m->data[i] is a double * (we've dereferenced the double ** once), we have to allocate doubles to store in that pointer.
The code to handle malloc failure is quite tricky: we have to loop back over every previously added row and free it, then free(m->data), then free(m), then return NULL. You have to free everything in reverse order, because if you free m first then you don't have access to all of ms data (and you have to free all of that or else you leak memory).
for(size_t j = 0; j < width; j++) m->data[i][j] = fill;
This loops through all the elements of the row and fills them with the fill value. Not too bad compared to the above.
}
return m;
}
Once all that is done, we just return the m object. Users can now access m->data[1][2] and get the item in column 2, row 3. But before we're finished, since it took so much effort to create, this object will take a little effort to clean up when we're done. Let's make a cleanup function:
void free_Matrix(struct Matrix *m)
{
for(size_t i = 0; i < height; i++) free(m->data[i]);
free(m->data);
free(m);
}
This is doing (basically) what we had to do in case of allocation failure in the (let's go ahead and call it a) constructor, so if you get all that this should be cake.
It should be noted that this is not necessarily the best way to implement a matrix. If you require users to call a get(matrix, i, j) function for array access instead of directly indexing the data via matrix->data[i][j], you can condense the (complex) double ** allocation into a flat array, and manually perform the indexing via multiplication in your access functions. If you have C99 (or are willing to jump through some hoops for C89 support) you can even make the flat matrix data a part of your struct Matrix object allocation with a flexible array member, thus allowing you to deallocate your object with a single call to free. But if you understand how the above works, you should be well on your way to implementing either of those solutions.
As noted by #Chris Lutz, it's easier to start from scratch. As you can see from the other answers, you should normally use an integer type (e.g. size_t) to specify array lengths, and you should allocate not only the pointers, but also the structures where they are stored. And one more thing: you should always check the result of allocation (if malloc returned NULL). Always.
An idea: store 2D array in a 1D array
What I'd like to add: often it is much better to store entire matrix as a contiguous block of elements, and do just one array allocation. So the matrix structure becomes something like this:
#include <stdlib.h>
#include <stdio.h>
/* allocate a single contiguous block of elements */
typedef struct c_matrix_t {
size_t w;
size_t h;
double *elems; /* contiguos block, row-major order */
} c_matrix;
The benefits are:
you have to allocate memory only once (generally, a slow and unpredictable operation)
it's easier to handle allocation errors (you do not need to free all previously allocated rows if the last row is not allocated, you have only one pointer to check)
you get a contuguous memory block, which may help writing some matrix algorithms effectively
Probably, it is also faster (but this should be tested first).
The drawbacks:
you cannot use m[i][j] notation, and have to use special access functions (see get and set below).
Get/set elements
Here they are, the function to manipulate such a matrix:
/* get an element pointer by row and column numbers */
double* getp(c_matrix *m, size_t const row, size_t const col) {
return (m->elems + m->w*row + col);
}
/* access elements by row and column numbers */
double get(c_matrix *m, size_t const row, size_t const col) {
return *getp(m, row, col);
}
/* set elements by row and column numbers */
void set(c_matrix *m, size_t const row, size_t const col, double const val) {
*getp(m, row, col) = val;
}
Memory allocation
Now see how you can allocate it, please note how much simpler this allocation method is:
/* allocate a matrix filled with zeros */
c_matrix *alloc_c_matrix(size_t const w, size_t const h) {
double *pelems = NULL;
c_matrix *pm = malloc(sizeof(c_matrix));
if (pm) {
pm->w = w;
pm->h = h;
pelems = calloc(w*h, sizeof(double));
if (!pelems) {
free(pm); pm = NULL;
return NULL;
}
pm->elems = pelems;
return pm;
}
return NULL;
}
We allocate a matrix structure first (pm), and if this allocation is successful, we allocate an array of elements (pelem). As the last allocation may also fail, we have to rollback all the allocation we already made to this point. Fortunately, with this approach there is only one of them (pm).
Finally, we have to write a function to free the matrix.
/* free matrix memory */
void free_c_matrix(c_matrix *m) {
if (m) {
free(m->elems) ; m->elems = NULL;
free(m); m = NULL;
}
}
As the original free (3) doesn't take any action when it receives a NULL pointer, so neither our free_c_matrix.
Test
Now we can test the matrix:
int main(int argc, char *argv[]) {
c_matrix *m;
int i, j;
m = alloc_c_matrix(10,10);
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
set(m, i, j, i*10+j);
}
}
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
printf("%4.1f\t", get(m, i, j));
}
printf("\n");
}
free_c_matrix(m);
return 0;
}
It works. We can even run it through Valgrind memory checker and see, that it seems to be OK. No memory leaks.