Simple memory allocation for embedded application - c

I need to have dynamic memory allocation without the use of malloc in an embedded application.
As we have enough RAM, I would like to allocate a big array (A[A_MAX]) on startup and have buffer arrays (B[]) within this one big array.
They would always begin at A[0] and be as long as they need (at max A_MAX, but mostly shorter).
Example:
at start up:
A[8] = {0,0,0,0,0,0,0,0};
declaring B[4] at A[0] and filling B with ones
B[4] = {1,1,1,1};
now A should look like this:
A[8] = {1,1,1,1,0,0,0,0}
How can I do this?
I looked at the sourcecode for malloc() and it does return the address of the next free part of the heap.
but when I use
float *B[4] = &A[0];
my compiler returns an error (invalid initializer)

As #neon mentioned I wanted to write an address to a float array.
Writing it like float *B = A[0] worked like a charm.

You may do:
#include <stdalign.h>
#define A_MAX 8
alignas(max_align_t) char _memory[A_MAX] = {0};
then you can just use pointers:
int main() {
{
float *floatdata = (void*)_memory;
// use floatdata
}
{
int *intdata = (void*)_memory;
// use intdata
}
}
I would write a handy function to calculate the maximum size for error checking:
// query the max size and allocate
inline void *dataalloc(size_t elemsize, size_t *n) {
*n = sizeof(_data) / elemsize;
return _data;
}
and do:
size_t size;
float *floatdata = dataalloc(sizeof(*floatdata), &size);
// use as-if floatdata[size]
for (size_t i = 0; i < size; ++i) floatdata[i] = i;

do you mean something like ? I'm using pointers to the array
#include <stdio.h>
#include <stdlib.h>
void allocator(float* src,int SrcSize,float **dst,int size,int pos){
if(size <= SrcSize)
for(int i=0;i<size;i++){
dst[i] = &(src+pos)[i];
}
}
int main()
{
float A[8] = {0,0,0,0,0,0,0,0};
float *B[4];
float *C[4];
allocator(A,sizeof(A)/sizeof(float),B,4,0);
*B[2] = 4;
allocator(A,sizeof(A)/sizeof(float),C,4,4);
*C[0] = 6;
printf("A[2] value is : %f\n" , A[2]); // output is 4.000
printf("A[4] value is : %f\n" , A[4]); // output is 6.000
return 0;
}

Related

How to return an array from function A and then function B takes this array

I have two functions in my main function.
I've tried to accomplish this problem with pointers, but as a beginner, it is very complicated to work with this.
int main(){
int *p;
p = function_A();
function_B(p);
return 0;
}
int function_A(){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
int function_B(int *myPointer){
// Here I just want to print my array I've got from function_A() to the
// console
printf("%d", *myPointer)
return 0;
}
function_A should return a array and function_B should take this array.
Thanks!
There are some issues your compiler will already have told you.
First, you should define the functions before calling them, or at least forward declare them.
Second, to return an array, you need to return a pointer to the first element of this array, i.e. return type is int * and not int.
Third, as FredK pointed out, when you receive just a pointer, you have no chance to determine how many elements are in the array it points to. You can either terminate the array with a specific value, e.g. 0, or you need to return the size of the array, too.
See the following adaptions made to your program:
int* function_A(int *size){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
if (size) {
*size = 3;
}
return myArray;
}
void function_B(int *myPointer, int size){
for (int i=0; i<size; i++) {
printf("%d\n", myPointer[i]);
}
}
int main(){
int *p;
int size=0;
p = function_A(&size);
function_B(p,size);
return 0;
}
Note: a reference to an array degrades to the address of the first byte of the array.
the following proposed code:
cleanly compiles
incorporates the comments to the question
assumes the programmer already knows the size of the array
performs the desired functionality
appended '\n' to format string of calls to printf() so output on separate lines
and now, the proposed code:
#include <stdio.h>
int * function_A( void );
void function_B(int *myPointer);
int main( void )
{
int *p;
p = function_A();
function_B(p);
return 0;
}
int * function_A()
{
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
void function_B(int *myPointer)
{
printf("%d\n", myPointer[0]);
printf("%d\n", myPointer[1]);
printf("%d\n", myPointer[2]);
}
a run of the program produces the following output:
11
22
33
Let's say you have a function that creates an array of ints:
int *create_int_array(const size_t num)
{
int *iarray;
size_t i;
if (num < 1)
return NULL; /* Let's not return an empty array. */
iarray = malloc(num * sizeof iarray[0]);
if (!iarray)
return NULL; /* Out of memory! */
/* Fill in the array with increasing integers. */
for (i = 0; i < num; i++)
iarray[i] = i + 1;
return iarray;
}
Let's say tou have a function that calculates the sum of the integers in the array. If we ignore any overflow issues, it could look like this:
int sum_int_array(const int *iarray, const size_t num)
{
int sum = 0;
size_t i;
/* Sum of an empty array is 0. */
if (num < 1)
return 0;
for (i = 0; i < num; i++)
sum += iarray[i];
return sum;
}
Note that sizeof is not a function, but a C language keyword. Its argument is only examined for its size. Thus, sizeof iarray[0] yields the size of each element in iarray, and is completely safe and valid even if iarray is undefined or NULL at that point. You see that idiom a lot in C programs; learn to read it as "size of first element of iarray", which is the same as "size of each element in iarray", because all C array elements have the exact same size.
In your main(), you could call them thus:
#ifndef NUM
#define NUM 5
#endif
int main(void)
{
int *array, result;
array = create_int_array(NUM);
if (!array) {
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
result = sum_int_array(array, NUM);
printf("Sum is %d.\n", result);
free(array);
return EXIT_SUCCESS;
}
As you can see, there is really not much to it. Well, you do need to get familiar with the pointer syntax.
(The rule I like to point out is that when reading pointer types, read the specifiers from right to left, delimited by * read as a pointer to. Thus, int *const a reads as "a is a const, a pointer to int", and const char **b reads as "b is a pointer to a pointer to const char".)
In this kind of situations, a structure describing an array makes much more sense. For example:
typedef struct {
size_t max; /* Maximum number of elements val[] can hold */
size_t num; /* Number of elements in val[] */
int *val;
} iarray;
#define IARRAY_INIT { 0, 0, NULL }
The idea is that you can declare a variable of iarray type just as you would any other variable; but you also initialize those to an empty array using the IARRAY_INIT macro. In other words, thus:
iarray my_array = IARRAY_INIT;
With that initialization, the structure is always initialized to a known state, and we don't need a separate initialization function. We really only need a couple of helper functions:
static inline void iarray_free(iarray *array)
{
if (array) {
free(array->val);
array->max = 0;
array->num = 0;
array->val = NULL;
}
}
/* Try to grow the array dynamically.
Returns the number of elements that can be added right now. */
static inline size_t iarray_need(iarray *array, const size_t more)
{
if (!array)
return 0;
if (array->num + more > array->max) {
size_t max = array->num + more;
void *val;
/* Optional: Growth policy. Instead of allocating exactly
as much memory as needed, we allocate more,
in the hopes that this reduces the number of
realloc() calls, which tend to be a bit slow.
However, we don't want to waste too much
memory by allocating and then not using it. */
if (max < 16) {
/* Always allocate at least 16 elements, */
max = 16;
} else
if (max < 65536) {
/* up to 65535 elements add 50% extra, */
max = (3*max) / 2;
} else {
/* then round up to next multiple of 65536, less 16. */
max = (max | 65535) + 65521;
}
val = realloc(array->val, max * sizeof array->val[0]);
if (!val) {
/* We cannot grow the array. However, the old
array is still intact; realloc() does not
free it if it fails. */
return array->max - array->num;
}
/* Note: the new elements in array->val,
array->val[array->max] to
array->val[max-1], inclusive,
are undefined. That is fine, usually,
but might be important in some special
cases like resizing hash tables or such. */
array->max = max;
array->val = val;
}
return array->max - array->num;
}
/* Optional; same as initializing the variable to IARRAY_INIT. */
static inline void iarray_init(iarray *array)
{
array->max = 0;
array->num = 0;
array->val = NULL;
}
The static inline bit means that the functions are only visible in this compilation unit, and the compiler is free to implement the function directly at the call site. Basically, static inline is used for macro-like functions and accessor functions. If you put the structure in a header file (.h), you'd put the related static inline helper functions in it as well.
The growth policy part is only an example. If you omit the growth policy, and always reallocate to array->num + more elements, your code will call realloc() very often, potentially for every int appended. In most cases, doing it that often will slow down your program, because realloc() (as well as malloc(), calloc()) is kind-of slow. To avoid that, we prefer to pad or round up the allocation a bit: not too much to waste allocated but unused memory, but enough to keep the overall program fast, and not bottlenecked on too many realloc() calls.
A "good growth policy" is very much up to debate, and really depends on the task at hand. The above one should work really well on all current operating systems on desktop machines, laptops, and tablets, when the program needs only one or only a handful of such arrays.
(If a program uses many such arrays, it might implement an iarray_optimize() function, that reallocates the array to exactly the number of elements it has. Whenever an array is unlikely to change size soon, calling that function will ensure not too much memory is sitting unused but allocated in the arrays.)
Let's look at an example function that uses the above. Say, the obvious one: appending an integer to the array:
/* Append an int to the array.
Returns 0 if success, nonzero if an error occurs.
*/
int iarray_append(iarray *array, int value)
{
if (!array)
return -1; /* NULL array specified! */
if (iarray_need(array, 1) < 1)
return -2; /* Not enough memory to grow the array. */
array->val[array->num++] = value;
return 0;
}
Another example function would be one that sorts the ints in an array by ascending or descending value:
static int cmp_int_ascending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? -1 :
(val1 > val2) ? +1 : 0;
}
static int cmp_int_descending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? +1 :
(val1 > val2) ? -1 : 0;
}
static void iarray_sort(iarray *array, int direction)
{
if (array && array->num > 1) {
if (direction > 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_ascending);
else
if (direction < 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_descending);
}
}
Many new programmers do not realize that the standard C library has that nifty and quite efficient qsort() function for sorting arrays; all it needs is a comparison function. If the direction is positive for iarray_sort(), the array is sorted in ascending order, smallest int first; if direction is negative, then in descending order, largest int first.
A simple example main() that reads in all valid ints from standard input, sorts them, and prints them in ascending order (increasing value):
int main(void)
{
iarray array = IARRAY_INIT;
int value;
size_t i;
while (scanf(" %d", &value) == 1)
if (iarray_append(&array, value)) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
iarray_sort(&array, +1); /* sort by increasing value */
for (i = 0; i < array.num; i++)
printf("%d\n", array.val[i]);
iarray_free(&array);
return EXIT_SUCCESS;
}
If size of array is indeed 3 (or other small fixed value), then you can simply use structs as values, something like:
struct ints3 {
int values[3];
// if needed, can add other fields
}
int main(){
struct ints3 ints;
ints = function_A();
function_B(&ints);
return 0;
}
// note about function_A signature: void is important,
// because in C empty () means function can take any arguments...
struct ints3 function_A(void) {
// use C designated initialiser syntax to create struct value,
// and return it directly
return (struct ints3){ .values = { 11, 22, 33 } };
}
int function_B(const struct ints3 *ints) {
// pass struct as const pointer to avoid copy,
// though difference to just passing a value in this case is insignificant
// could use for loop, see other answers, but it's just 3 values, so:
printf("%d %d %d\n", ints->values[0], ints->values[1], ints->values[2]);
return 0; // does this function really need return value?
}

C malloc of pointer to pointer inside function not giving correct size

So I am now rewriting my fortran code in C (to use CUDA), and apparently I do not understand how to properly use malloc and pointers. I am trying to make the main function just calls to other functions, which need to malloc arrays that will then be used inside other functions. So, I am passing pointers of pointers to them as per this post: C Programming: malloc() inside another function
But the right amount of memory is not being allocated so I get segmentation faults. Here is the code:
#include <stdio.h>
#include <stdlib.h>
//#include <cuda.h>
#include <math.h>
//#include "cublas.h"
//datatype to match FORTRAN complex type
typedef float real;
typedef struct{
int nx;
int ny;
int nz;
int sz;
int tz;
} states;
void set_SPB(real **,int,states **,states **,int **);
//void set_SPB();
int find_minimum(int a[], int n,int start);
const real hc =197.32697,pi=3.1415927;
int main(){
int nmax = 2, A = 28;
real *etemp, *fock;
int *Ndex,*lookup,*lookup_a;
states *channel,*SPB;
//!generates the single particle basis to be used
set_SPB(&etemp,nmax,&SPB,&channel,&Ndex);
free(etemp);
free(Ndex);
free(SPB);
return 0;
}
void set_SPB(real **etemp,int nmax,states **SPB,states **channel,int **Ndex){
int tot_orbs = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*4;
int D = tot_orbs/4;
int Nalpha = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*9;
real E;
*etemp = (real*)malloc(D);
*Ndex = (int*)malloc(D*3);
*SPB = (states*)malloc(tot_orbs);
printf("orbits without spin degeneracy %d \n",D);
printf("size of etemp %ld \n",sizeof(*etemp)/sizeof(*etemp[0]));
return;
int i = 0;
for(int nx =-nmax;nx<=nmax;nx++){
for(int ny =-nmax;ny<=nmax;ny++){
for(int nz =-nmax;nz<=nmax;nz++){
E = 0.5*4.0*pi*pi*(nx*nx+ny*ny+nz*nz);
//printf("%d\n",i);
*etemp[i] = E;
*Ndex[0*D+i] =nx;
*Ndex[1*D+i] = ny;
*Ndex[2*D+i] = nz;
i+=1;
}
}
}
return;
}
Also I am not sure exactly if my assignments of the arrays are correct.
Specifically the print to find the number of elements of that have been allocated always gives 2, when it should be D = 125.
I cannot believe that float and int take only 1 byte in your environment.
Multiply the size to be allocated by size of their elements.
*etemp = malloc(sizeof(**etemp) * D);
*Ndex = malloc(sizeof(**Ndex) * D*3);
*SPB = malloc(sizeof(**SPB) * tot_orbs); /* not sure because this is not used */
Note that they say you shouldn't cast the result of malloc() in C.
Also note that [] operator has higher precedence than * operator, so you have to use parentheses to use the arrays.
(*etemp)[i] = E;
(*Ndex)[0*D+i] =nx;
(*Ndex)[1*D+i] = ny;
(*Ndex)[2*D+i] = nz;

How to allocate and declare a 3D of array of structs in C?

How do you allocate and declare a 3D array of structs in C?
Do you first allocate the array or declare it?
I feel like you have to allocate it first so you can declare it so it is on the heap, but then how do you allocate something that hasn't been made yet?
Also, should you allocate it all at once or element by element?
Also am i putting the structs into the array correctly?
My guess on how to do it would be:
header.h
struct myStruct{
int a;
int b;
};
typedef struct myStruct myStruct_t;
main.c
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
int main(void){
int length=2;
int height=3;
int width =4;
myStruct_t *elements;
struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct);
//zero based array
arr[length-1][height-1][width-1];
int x=0;
while(x<length){
int y=0;
while(y<height){
int z=0;
while(z<depth){
arr[x][y][z].a=rand();
arr[x][y][z].b=rand();
z++;
}
y++;
}
x++;
}
return 0;
}
The easy way is:
myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );
Then your loop can access arr2[x][y][z].a = rand(); and so on. If you're not familiar with this way of calling calloc, see here. As usual with malloc, check arr2 against NULL before proceeding.
The triple-pointer approach is not really a practical solution. If your compiler does not support variably-modified types then the array should be flattened to 1-D.
There are a couple of different ways to do this, depending on what you want. First, you can allocate your array on the stack (in C99 and some compilers) like this:
myStruct_t arr[length][height][depth];
If you want it allocated on the heap, then you can do a single allocation of the appropriate size. You can then either do the index calculation yourself or make a pointer do the work for you (in C99 and some compilers):
void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;
/* TODO: check return of malloc */
...
arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */
arr2[x][y][z].b = rand(); /* indexing the C99 way */
Or you can manually allocate the multiple dimensions.
#include <stddef.h>
#include <stdlib.h>
typedef struct myStruct
{
int a, b;
} myStruct_t;
int main()
{
myStruct_t ***arr;
int length = 5000, height = 1000, depth = 20;
int x, y, z;
int ret = 1;
if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
goto FAIL;
for (x = 0; x < length; ++x)
{
if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
goto FAIL_X;
for (y = 0; y < height; ++y)
{
if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
goto FAIL_Y;
for (z = 0; z < depth; ++z)
{
arr[x][y][z].a = rand();
arr[x][y][z].b = rand();
}
}
}
/* TODO: rest of program logic */
/* program successfully completed */
ret = 0;
/* reclaim arr */
FAIL_CLEANUP: /* label used by TODO code that fails */
for (x = length - 1; x >= 0; --x)
{
for (y = height - 1; y >= 0; --y)
{
free(arr[x][y]);
FAIL_Y:
;
}
free(arr[x]);
FAIL_X:
;
}
free(arr);
FAIL:
return ret;
}
This last version uses a lot more memory for all the explicit pointers it contains, its memory locality is worse and it's significantly more complex to properly allocate and reclaim. However, it does allow different sizes along your dimensions. For example, the array arr[0][4] can have a different size than arr[0][7] if you ever need that.
If you want to allocate it on the heap, then you probably want the second version with a single allocation and multi-dimension pointer (if available) or do the indexing yourself manually using appropriate math.

How to initialize an array with values to later be realloced in C

I've got about 12000 pre known values that I need to place in an array early in the program. Given certain circumstances, I will later need to resize this array with realloc. Is there any way to initialize an array with malloc/calloc with values, or fill an array with several other values?
You cannot initialize a malloced array this way, your best chance is to have it statically in your program, and copy it to a malloced array at the beginning of the run, e.g.:
static int arr[] = {1,2,3,4};
static int * malloced_arr;
// in the init function
malloced_arr = malloc(sizeof(arr));
if (malloced_arr)
{
memcpy(malloced_arr, arr, sizeof(arr));
}
This is the sort of thing that zero length arrays are useful for. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct values {
int x[4];
int y[0];
} V = { {1, 2, 3} };
int
main( int argc, char ** argv )
{
int *t;
int i;
struct values *Y;
(void) argc; (void) argv;
/* Allocate space for 100 more items */
Y = malloc( sizeof *Y + 100 * sizeof *Y->y );
t = Y->x;
memcpy( Y, &V, sizeof V );
t[3] = 4;
for( i = 0; i < 4; i++ )
printf( "%d: %d\n", i, t[ i ]);
return 0;
}
Of course, this is really just a parlor trick that gains you nothing over Binyamin's solution, and introduces a lot of totally unnecessary obfuscation.

2d array in C with negative indices

I am writing a C-program where I need 2D-arrays (dynamically allocated) with negative indices or where the index does not start at zero. So for an array[i][j] the row-index i should take values from e.g. 1 to 3 and the column-index j should take values from e.g. -1 to 9.
For this purpose I created the following program, here the variable columns_start is set to zero, so just the row-index is shifted and this works really fine.
But when I assign other values than zero to the variable columns_start, I get the message (from valgrind) that the command "free(array[i]);" is invalid.
So my questions are:
Why it is invalid to free the memory that I allocated just before?
How do I have to modify my program to shift the column-index?
Thank you for your help.
#include <stdio.h>
#include <stdlib.h>
main()
{
int **array, **array2;
int rows_end, rows_start, columns_end, columns_start, i, j;
rows_start = 1;
rows_end = 3;
columns_start = 0;
columns_end = 9;
array = malloc((rows_end-rows_start+1) * sizeof(int *));
for(i = 0; i <= (rows_end-rows_start); i++) {
array[i] = malloc((columns_end-columns_start+1) * sizeof(int));
}
array2 = array-rows_start; //shifting row-index
for(i = rows_start; i <= rows_end; i++) {
array2[i] = array[i-rows_start]-columns_start; //shifting column-index
}
for(i = rows_start; i <= rows_end; i++) {
for(j = columns_start; j <= columns_end; j++) {
array2[i][j] = i+j; //writing stuff into array
printf("%i %i %d\n",i, j, array2[i][j]);
}
}
for(i = 0; i <= (rows_end-rows_start); i++) {
free(array[i]);
}
free(array);
}
When you shift column indexes, you assign new values to original array of columns: in
array2[i] = array[i-rows_start]-columns_start;
array2[i] and array[i=rows_start] are the same memory cell as array2 is initialized with array-rows_start.
So deallocation of memory requires reverse shift. Try the following:
free(array[i] + columns_start);
IMHO, such modification of array indexes gives no benefit, while complicating program logic and leading to errors. Try to modify indexes on the fly in single loop.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a[] = { -1, 41, 42, 43 };
int *b;//you will always read the data via this pointer
b = &a[1];// 1 is becoming the "zero pivot"
printf("zero: %d\n", b[0]);
printf("-1: %d\n", b[-1]);
return EXIT_SUCCESS;
}
If you don't need just a contiguous block, then you may be better off with hash tables instead.
As far as I can see, your free and malloc looks good. But your shifting doesn't make sense. Why don't you just add an offset in your array instead of using array2:
int maxNegValue = 10;
int myNegValue = -6;
array[x][myNegValue+maxNegValue] = ...;
this way, you're always in the positive range.
For malloc: you acquire (maxNegValue + maxPosValue) * sizeof(...)
Ok I understand now, that you need free(array.. + offset); even using your shifting stuff.. that's probably not what you want. If you don't need a very fast implementation I'd suggest to use a struct containing the offset and an array. Then create a function having this struct and x/y as arguments to allow access to the array.
I don't know why valgrind would complain about that free statement, but there seems to be a lot of pointer juggling going on so it doesn't surprise me that you get this problem in the first place. For instance, one thing which caught my eye is:
array2 = array-rows_start;
This will make array2[0] dereference memory which you didn't allocate. I fear it's just a matter of time until you get the offset calcuations wrong and run into this problem.
One one comment you wrote
but im my program I need a lot of these arrays with all different beginning indices, so I hope to find a more elegant solution instead of defining two offsets for every array.
I think I'd hide all this in a matrix helper struct (+ functions) so that you don't have to clutter your code with all the offsets. Consider this in some matrix.h header:
struct matrix; /* opaque type */
/* Allocates a matrix with the given dimensions, sample invocation might be:
*
* struct matrix *m;
* matrix_alloc( &m, -2, 14, -9, 33 );
*/
void matrix_alloc( struct matrix **m, int minRow, int maxRow, int minCol, int maxCol );
/* Releases resources allocated by the given matrix, e.g.:
*
* struct matrix *m;
* ...
* matrix_free( m );
*/
void matrix_free( struct matrix *m );
/* Get/Set the value of some elment in the matrix; takes logicaly (potentially negative)
* coordinates and translates them to zero-based coordinates internally, e.g.:
*
* struct matrix *m;
* ...
* int val = matrix_get( m, 9, -7 );
*/
int matrix_get( struct matrix *m, int row, int col );
void matrix_set( struct matrix *m, int row, int col, int val );
And here's how an implementation might look like (this would be matrix.c):
struct matrix {
int minRow, maxRow, minCol, maxCol;
int **elem;
};
void matrix_alloc( struct matrix **m, int minCol, int maxCol, int minRow, int maxRow ) {
int numRows = maxRow - minRow;
int numCols = maxCol - minCol;
*m = malloc( sizeof( struct matrix ) );
*elem = malloc( numRows * sizeof( *elem ) );
for ( int i = 0; i < numRows; ++i )
*elem = malloc( numCols * sizeof( int ) );
/* setting other fields of the matrix omitted for brevity */
}
void matrix_free( struct matrix *m ) {
/* omitted for brevity */
}
int matrix_get( struct matrix *m, int col, int row ) {
return m->elem[row - m->minRow][col - m->minCol];
}
void matrix_set( struct matrix *m, int col, int row, int val ) {
m->elem[row - m->minRow][col - m->minCol] = val;
}
This way you only need to get this stuff right once, in a central place. The rest of your program doesn't have to deal with raw arrays but rather the struct matrix type.

Resources