How to ensure a 2D array is allocated contigously in memory - c

I am sending a 2D array over MPI and for this to work correctly the array needs to be contiguously allocated in memory.
I am allocating it as follows:
int **array;
array = malloc(size1 * sizeof( *(array) );
for (int k = 0; k < size1; k++)
array[k] = malloc(size2 * sizeof(**(array));
Then I would like to use:
MPI_Send(array, size1*size2, MPI_INT, target_pe, tag, MPI_COMM_WORLD);
How can I ensure the array is allocated contiguously?
Currently I am trying this:
for (int k = 0; k < size1; k++)
MPI_Send(array[k], size2, MPI_INT, target_pe, tag, MPI_COMM_WORLD);
which leads to a seg fault later in an unrelated part of the program. However if I send the elements 1 by 1 it works.

How to ensure a 2D array is allocated contiguously in memory
Allocate in one step.
Example uses C99 code which supports variable length arrays. Here a pointer to a VLA is used.
// ptr is a pointer to a 2D array
int (*ptr)[size1][size2] = malloc(sizeof *ptr);
(*ptr)[0][0] = 1; // One corner of the 2D array
(*ptr)[size-1][size-1] = 2; // Opposite corner of the 2D array
I'll look into sample MPI() code later.

Use:
int (*array)[size2] = malloc(size1 * sizeof *array);
if (!array) Handle error…
If size2 is not a constant and your C implementation does not support variable length arrays, then use:
int *array = malloc(size1 * size2 * sizeof *array);
if (!array) Handle error…
In this case, you will have to use manual address arithmetic to access array elements. Instead of array[i][j], use array[i*size2 + j].

You can not ensure that by using sequential calls to malloc(). What you can do instead, you can allocate from the beginning malloc(size1 * size2) space in the memory, then you can split your allocated buffer how you desire. You can now say that array[i] is in fact array[i * size2] in the memory.

The correct way is to allocate the memory for the 2D array in on single operation. Then as arrays are not really first class citizens in C, not speaking of multi-dimensional arrays, you will have to allocate memory for an array of pointers and make its elements points to the beginning of each row:
int *mem = malloc(sizeof(*mem) * size1 * size2);
int **array = malloc(size1 * sizeof(*array));
for (int k = 0; k < size1; k++) {
array[k] = mem + k * size2 * sizeof(*mem);
}
This will ensure contiguous allocation when it matters for passing the array to routine expecting that, and still allow to access the elements as array[i][j];

Related

Dynamic Memory Allocation for 2D Arrays in C

I'm reading about dynamic memory allocation for 2D arrays, and I'm looking at this example:
int nrows = 2;
int ncols = 5;
char **pvowels = malloc(nrows * sizeof(char));
pvowels[0] = malloc(ncols * sizeof(char));
pvowels[1] = malloc(ncols * sizeof(char));
My understanding is that the 2nd and 3rd malloc both allocate memory the size of 5 chars and pvowels[0] and pvowels[1] point to each, but I'm having trouble understanding the first malloc.
The first malloc looks like it allocates memory the size of 2 chars, and uses it to store the two pointers. But isn't a char only 256 possible values, and pointers can go up to billions? So if it's allocating memory for storing pointers, doesn't it need to be bigger than chars?
Firstly, your first malloc() is incorrect. Using nrows * sizeof(char) only allocates 2 bytes, whereas you need 2 rows of char* pointers. You have to allocate like this instead:
char **pvowels = malloc(nrows * sizeof(char*));
Or:
char **pvowels = malloc(nrows * sizeof(*pvowels));
Also note that char **pvowels is not a 2D array, but simply a pointer to a char pointer. If you were using a 2D array, such as char pvowels[][], you wouldn't need to dynamically allocate pointers on the heap. You could also just use a 2D array for your problem, such as char pvowels[2][5], as ncols and nrows seems to be fixed in this case.
Secondly, your allocations for pvowels[0] and pvowels[1] will only make space for 4 valid characters, such as "abcd", because 1 space is needed for the null terminating character \0. You should write instead:
pvowels[0] = malloc(ncols+1); /* +1 for '\0' */
pvowels[1] = malloc(ncols+1);
Note: sizeof(char) is always 1, so their is no need to include it. You should also check that malloc() returned NULL or not.
Allocating for an array of nrows pointers to char, and then separately allocating for nrows arrays of ncols chars has a disadvantage, in that the separate memory allocations are not guaranteed to be contiguous in memory. This fragmentation can lead to performance penalties.
A better approach is to allocate enough memory to hold a 2d array, and assign the resulting pointer to a pointer to an array of ncols chars. As shown here, this approach does rely on VLA's, but these have been a part of C since C99. This has the advantage of allocating memory at once, with only one allocation to free.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t nrows = 2;
size_t ncols = 5;
/* Allocate space for a 2d array */
char (*pvowels)[ncols] = malloc(sizeof (char[nrows][ncols]));
/* Another alternative */
// char (*pvowels)[ncols] = malloc(nrows * ncols);
if (pvowels == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
pvowels[i][j] = 'a' + i * ncols + j;
}
}
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
printf("%5c", pvowels[i][j]);
}
putchar('\n');
}
free(pvowels);
return 0;
}
Program output:
a b c d e
f g h i j
char **pvowels is a pointer to a pointer, meaning it behaves like an array declared like this:
char * pvowels[a number];
So basically, pointers to chars, and not pointers are being assigned in the example you provided.
A simple and easy to understand code:(Using just a single pointer to store and access)
#include<stdio.h>
#include<stdlib.h>
int main(){
int *a,n,r,c,i,j;
scanf("%d",&n);
r=c=n;
a=(int *)malloc(r*c*sizeof(int));
for(i=0;i<r;i++)
{
for(j=0;j<c;j++){
scanf("%d",(a+i*c+j));
}
}
for(i=0;i<r;i++)
{
for(j=0;j<c;j++){
printf("%d",*(a+i*c+j));
}
}
}
References: geeksforgeeks.org

Dynamically creating a 2 dimensional array of pointers in c [duplicate]

Does someone know how I can use dynamically allocated multi-dimensional arrays using C? Is that possible?
Since C99, C has 2D arrays with dynamical bounds. If you want to avoid that such beast are allocated on the stack (which you should), you can allocate them easily in one go as the following
double (*A)[n] = malloc(sizeof(double[n][n]));
and that's it. You can then easily use it as you are used for 2D arrays with something like A[i][j]. And don't forget that one at the end
free(A);
Randy Meyers wrote series of articles explaining variable length arrays (VLAs).
With dynamic allocation, using malloc:
int** x;
x = malloc(dimension1_max * sizeof(*x));
for (int i = 0; i < dimension1_max; i++) {
x[i] = malloc(dimension2_max * sizeof(x[0]));
}
//Writing values
x[0..(dimension1_max-1)][0..(dimension2_max-1)] = Value;
[...]
for (int i = 0; i < dimension1_max; i++) {
free(x[i]);
}
free(x);
This allocates an 2D array of size dimension1_max * dimension2_max. So, for example, if you want a 640*480 array (f.e. pixels of an image), use dimension1_max = 640, dimension2_max = 480. You can then access the array using x[d1][d2] where d1 = 0..639, d2 = 0..479.
But a search on SO or Google also reveals other possibilities, for example in this SO question
Note that your array won't allocate a contiguous region of memory (640*480 bytes) in that case which could give problems with functions that assume this. So to get the array satisfy the condition, replace the malloc block above with this:
int** x;
int* temp;
x = malloc(dimension1_max * sizeof(*x));
temp = malloc(dimension1_max * dimension2_max * sizeof(x[0]));
for (int i = 0; i < dimension1_max; i++) {
x[i] = temp + (i * dimension2_max);
}
[...]
free(temp);
free(x);
Basics
Arrays in c are declared and accessed using the [] operator. So that
int ary1[5];
declares an array of 5 integers. Elements are numbered from zero so ary1[0] is the first element, and ary1[4] is the last element. Note1: There is no default initialization, so the memory occupied by the array may initially contain anything. Note2: ary1[5] accesses memory in an undefined state (which may not even be accessible to you), so don't do it!
Multi-dimensional arrays are implemented as an array of arrays (of arrays (of ... ) ). So
float ary2[3][5];
declares an array of 3 one-dimensional arrays of 5 floating point numbers each. Now ary2[0][0] is the first element of the first array, ary2[0][4] is the last element of the first array, and ary2[2][4] is the last element of the last array. The '89 standard requires this data to be contiguous (sec. A8.6.2 on page 216 of my K&R 2nd. ed.) but seems to be agnostic on padding.
Trying to go dynamic in more than one dimension
If you don't know the size of the array at compile time, you'll want to dynamically allocate the array. It is tempting to try
double *buf3;
buf3 = malloc(3*5*sizeof(double));
/* error checking goes here */
which should work if the compiler does not pad the allocation (stick extra space between the one-dimensional arrays). It might be safer to go with:
double *buf4;
buf4 = malloc(sizeof(double[3][5]));
/* error checking */
but either way the trick comes at dereferencing time. You can't write buf[i][j] because buf has the wrong type. Nor can you use
double **hdl4 = (double**)buf;
hdl4[2][3] = 0; /* Wrong! */
because the compiler expects hdl4 to be the address of an address of a double. Nor can you use double incomplete_ary4[][]; because this is an error;
So what can you do?
Do the row and column arithmetic yourself
Allocate and do the work in a function
Use an array of pointers (the mechanism qrdl is talking about)
Do the math yourself
Simply compute memory offset to each element like this:
for (i=0; i<3; ++i){
for(j=0; j<3; ++j){
buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about
padding in this case */
}
}
Allocate and do the work in a function
Define a function that takes the needed size as an argument and proceed as normal
void dary(int x, int y){
double ary4[x][y];
ary4[2][3] = 5;
}
Of course, in this case ary4 is a local variable and you can not return it: all the work with the array must be done in the function you call of in functions that it calls.
An array of pointers
Consider this:
double **hdl5 = malloc(3*sizeof(double*));
/* Error checking */
for (i=0; i<3; ++i){
hdl5[i] = malloc(5*sizeof(double))
/* Error checking */
}
Now hdl5 points to an array of pointers each of which points to an array of doubles. The cool bit is that you can use the two-dimensional array notation to access this structure---hdl5[0][2] gets the middle element of the first row---but this is none-the-less a different kind of object than a two-dimensional array declared by double ary[3][5];.
This structure is more flexible then a two dimensional array (because the rows need not be the same length), but accessing it will generally be slower and it requires more memory (you need a place to hold the intermediate pointers).
Note that since I haven't setup any guards you'll have to keep track of the size of all the arrays yourself.
Arithmetic
c provides no support for vector, matrix or tensor math, you'll have to implement it yourself, or bring in a library.
Multiplication by a scaler and addition and subtraction of arrays of the same rank are easy: just loop over the elements and perform the operation as you go. Inner products are similarly straight forward.
Outer products mean more loops.
If you know the number of columns at compile time, it's pretty simple:
#define COLS ...
...
size_t rows;
// get number of rows
T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T
You can treat ap like any 2D array:
ap[i][j] = x;
When you're done you deallocate it as
free(ap);
If you don't know the number of columns at compile time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, it's still pretty simple:
size_t rows;
size_t cols;
// get rows and cols
T (*ap)[cols] = malloc(sizeof *ap * rows);
...
ap[i][j] = x;
...
free(ap);
If you don't know the number of columns at compile time and you're working with a version of C that doesn't support variable-length arrays, then you'll need to do something different. If you need all of the elements to be allocated in a contiguous chunk (like a regular array), then you can allocate the memory as a 1D array, and compute a 1D offset:
size_t rows, cols;
// get rows and columns
T *ap = malloc(sizeof *ap * rows * cols);
...
ap[i * rows + j] = x;
...
free(ap);
If you don't need the memory to be contiguous, you can follow a two-step allocation method:
size_t rows, cols;
// get rows and cols
T **ap = malloc(sizeof *ap * rows);
if (ap)
{
size_t i = 0;
for (i = 0; i < cols; i++)
{
ap[i] = malloc(sizeof *ap[i] * cols);
}
}
ap[i][j] = x;
Since allocation was a two-step process, deallocation also needs to be a two-step process:
for (i = 0; i < cols; i++)
free(ap[i]);
free(ap);
malloc will do.
int rows = 20;
int cols = 20;
int *array;
array = malloc(rows * cols * sizeof(int));
Refer the below article for help:-
http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf
Here is working code that defines a subroutine make_3d_array to allocate a multidimensional 3D array with N1, N2 and N3 elements in each dimension, and then populates it with random numbers. You can use the notation A[i][j][k] to access its elements.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Method to allocate a 2D array of floats
float*** make_3d_array(int nx, int ny, int nz) {
float*** arr;
int i,j;
arr = (float ***) malloc(nx*sizeof(float**));
for (i = 0; i < nx; i++) {
arr[i] = (float **) malloc(ny*sizeof(float*));
for(j = 0; j < ny; j++) {
arr[i][j] = (float *) malloc(nz * sizeof(float));
}
}
return arr;
}
int main(int argc, char *argv[])
{
int i, j, k;
size_t N1=10,N2=20,N3=5;
// allocates 3D array
float ***ran = make_3d_array(N1, N2, N3);
// initialize pseudo-random number generator
srand(time(NULL));
// populates the array with random numbers
for (i = 0; i < N1; i++){
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
ran[i][j][k] = ((float)rand()/(float)(RAND_MAX));
}
}
}
// prints values
for (i=0; i<N1; i++) {
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
printf("A[%d][%d][%d] = %f \n", i,j,k,ran[i][j][k]);
}
}
}
free(ran);
}
There's no way to allocate the whole thing in one go. Instead, create an array of pointers, then, for each pointer, create the memory for it. For example:
int** array;
array = (int**)malloc(sizeof(int*) * 50);
for(int i = 0; i < 50; i++)
array[i] = (int*)malloc(sizeof(int) * 50);
Of course, you can also declare the array as int* array[50] and skip the first malloc, but the second set is needed in order to dynamically allocate the required storage.
It is possible to hack a way to allocate it in a single step, but it would require a custom lookup function, but writing that in such a way that it will always work can be annoying. An example could be L(arr,x,y,max_x) arr[(y)*(max_x) + (x)], then malloc a block of 50*50 ints or whatever and access using that L macro, e.g.
#define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)]
int dim_x = 50;
int dim_y = 50;
int* array = malloc(dim_x*dim_y*sizeof(int));
int foo = L(array, 4, 6, dim_x);
But that's much nastier unless you know the effects of what you're doing with the preprocessor macro.
int rows, columns;
/* initialize rows and columns to the desired value */
arr = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
{
arr[i] = (int*)malloc(cols*sizeof(int));
}
// use new instead of malloc as using malloc leads to memory leaks
`enter code here
int **adj_list = new int*[rowsize];
for(int i = 0; i < rowsize; ++i)
{
adj_list[i] = new int[colsize];
}

Setup a 2D array, change size later - C

Is it possible to declare a 2D array in C, then set its size later on? I know in C you have to deal with memory and such, but I cannot find answer to this question despite all my searching.
My current example is..
int boardsize, linewin;
char array[1][1];
//boardsize is set within here.
array = [boardsize][boardsize];
With C you will need to do your own dynamic array management using pointers.
See the following articles on how to go about doing so using an allocated memory area.
Malloc a 2D array in C
Using malloc for allocation of multi-dimensional arrays with different row lengths
Since you are looking to modify these, you may also need to use the realloc() function or the free() function to release allocated memory.
For information about using the realloc() function look at the following stack overflow.
Realloc double 2D array in C
two-dimensional dynamic array (realloc in c)
EDIT - Adding an example
Here are two functions to malloc() a two dimensional array and to realloc() a two dimensional array. You could actually just use the realloc() version if you pass a NULL pointer to realloc2dCArray() for the memory area to be reallocated.
What I have tried to do is to use a single malloc() and realloc() for all of the memory needed so that you can free() the memory with a single call to free().
char **malloc2dCArray (int nRows, int nCols)
{
// use a single malloc for the char pointers to the first char of each row
// so we allocate space for the pointers and then space for the actual rows.
char **pArray = malloc (sizeof(char *) * nRows + sizeof(char) * nCols * nRows);
if (pArray) {
// calculate offset to the beginning of the actual data space
char *pOffset = (char *)(pArray + nRows);
int i;
// fix up the pointers to the individual rows
for (i = 0; i < nRows; i++) {
pArray[i] = pOffset;
pOffset += nCols;
}
}
return pArray;
}
char **realloc2dCArray (char **pOld, int nRows, int nCols)
{
// use a single realloc for the char pointers to the first char of each row
// so we reallocate space for the pointers and then space for the actual rows.
char **pArray = realloc (pOld, sizeof(char *) * nRows + sizeof(char) * nCols * nRows);
if (pArray) {
// calculate offset to the beginning of the actual data space
char *pOffset = (char *)(pArray + nRows);
int i;
// fix up the pointers to the individual rows
for (i = 0; i < nRows; i++) {
pArray[i] = pOffset;
pOffset += nCols;
}
}
return pArray;
}
To use these functions you would do something like the following:
char **pChars = malloc2dCArray (16, 8);
int i, j;
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
pChars[i][j] = 0;
}
}
To do a realloc() you will want to check that the realloc() worked so use a temporary variable and check for NULL before using it.
{
char **pChars2 = realloc2dCArray (pChars, 25, 8);
if (pChars2) pChars = pChars2;
}
You could also just use the realloc() version if you provide a NULL pointer since realloc() will do a malloc() if the pointer to the memory to realloc() is NULL.
I did some testing of this using a debugger and it looks like it is working to me.

Dynamically allocated 2 dimensional array

I am trying to build two dimensional array by dynamically allocating. My question is that is it possible that its first dimension would take 100 values, then second dimension would take variable amount of values depending on my problem? If it is possible then how I would access it? How would I know the second dimension's boundary?
(See the comments in the code)
As a result you'll get an array such like the following:
// Create an array that will contain required variables of the required values
// which will help you to make each row of it's own lenght.
arrOfLengthOfRows[NUMBER_OF_ROWS] = {value_1, value_2, ..., value_theLast};
int **array;
array = malloc(N * sizeof(int *)); // `N` is the number of rows, as on the pic.
/*
if(array == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
// Here we make each row of it's own, individual length.
for(i = 0; i < N; i++) {
array[i] = malloc(arrOfLengthOfRows[i] * sizeof(int));
/*
if(array[i] == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
}
You can use array of 100 pointers:
int *arr[100];
then you can dynamically allocate memory to each of the 100 pointers separately of any size you want, however you have to remember how much memory (for each pointer) you have allocated, you cannot expect C compiler to remember it or tell it to you, i.e. sizeof will not work here.
To access any (allowed, within boundary) location you can simply use 2D array notation e.g. to access 5th location of memory allocated to 20th pointer you can use arr[20][5] or *(arr[20] + 5).
I believe the OP wants a single chunk of memory for the array, and is willing to fix one of the dimensions to get it. I frequently like to do this when coding in C as well.
We all used to be able to do double x[4][]; and the compiler would know what to do. But someone has apparently messed that up - maybe even for a good reason.
The following however still works and allows us to use large chunks of memory instead of having to do a lot of pointer management.
#include <stdio.h>
#include <stdlib.h>
// double x[4][];
struct foo {
double y[4];
} * x;
void
main(int ac, char * av[])
{
double * dp;
int max_x = 10;
int i;
x = calloc(max_x, sizeof(struct foo));
x[0].y[0] = 0.23;
x[0].y[1] = 0.45;
x[9].y[0] = 1.23;
x[9].y[1] = 1.45;
dp = x[9].y;
for (i = 0; i < 4; i++)
if (dp[i] > 0)
printf("%f\n", dp[i]);
}
The trick is to declare the fixed dimension in a struct. But keep in mind that the "first" dimension is the dynamic dimension and the "second" one is fixed. And this is the opposite of the old way ...
You will have to track the size of your dynamic dimension on your own - sizeof can't help you with that.
Using anonymous thingies you might even be able to git rid of 'y'.
Using a single pointer:
int *arr = (int *)malloc(r * c * sizeof(int));
/* how to access array elements */
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count; //count initialized as, int count=0;
Using pointer to a pointer:
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
In this case you can access array elements same as you access statically allocated array.

How do I work with dynamic multi-dimensional arrays in C?

Does someone know how I can use dynamically allocated multi-dimensional arrays using C? Is that possible?
Since C99, C has 2D arrays with dynamical bounds. If you want to avoid that such beast are allocated on the stack (which you should), you can allocate them easily in one go as the following
double (*A)[n] = malloc(sizeof(double[n][n]));
and that's it. You can then easily use it as you are used for 2D arrays with something like A[i][j]. And don't forget that one at the end
free(A);
Randy Meyers wrote series of articles explaining variable length arrays (VLAs).
With dynamic allocation, using malloc:
int** x;
x = malloc(dimension1_max * sizeof(*x));
for (int i = 0; i < dimension1_max; i++) {
x[i] = malloc(dimension2_max * sizeof(x[0]));
}
//Writing values
x[0..(dimension1_max-1)][0..(dimension2_max-1)] = Value;
[...]
for (int i = 0; i < dimension1_max; i++) {
free(x[i]);
}
free(x);
This allocates an 2D array of size dimension1_max * dimension2_max. So, for example, if you want a 640*480 array (f.e. pixels of an image), use dimension1_max = 640, dimension2_max = 480. You can then access the array using x[d1][d2] where d1 = 0..639, d2 = 0..479.
But a search on SO or Google also reveals other possibilities, for example in this SO question
Note that your array won't allocate a contiguous region of memory (640*480 bytes) in that case which could give problems with functions that assume this. So to get the array satisfy the condition, replace the malloc block above with this:
int** x;
int* temp;
x = malloc(dimension1_max * sizeof(*x));
temp = malloc(dimension1_max * dimension2_max * sizeof(x[0]));
for (int i = 0; i < dimension1_max; i++) {
x[i] = temp + (i * dimension2_max);
}
[...]
free(temp);
free(x);
Basics
Arrays in c are declared and accessed using the [] operator. So that
int ary1[5];
declares an array of 5 integers. Elements are numbered from zero so ary1[0] is the first element, and ary1[4] is the last element. Note1: There is no default initialization, so the memory occupied by the array may initially contain anything. Note2: ary1[5] accesses memory in an undefined state (which may not even be accessible to you), so don't do it!
Multi-dimensional arrays are implemented as an array of arrays (of arrays (of ... ) ). So
float ary2[3][5];
declares an array of 3 one-dimensional arrays of 5 floating point numbers each. Now ary2[0][0] is the first element of the first array, ary2[0][4] is the last element of the first array, and ary2[2][4] is the last element of the last array. The '89 standard requires this data to be contiguous (sec. A8.6.2 on page 216 of my K&R 2nd. ed.) but seems to be agnostic on padding.
Trying to go dynamic in more than one dimension
If you don't know the size of the array at compile time, you'll want to dynamically allocate the array. It is tempting to try
double *buf3;
buf3 = malloc(3*5*sizeof(double));
/* error checking goes here */
which should work if the compiler does not pad the allocation (stick extra space between the one-dimensional arrays). It might be safer to go with:
double *buf4;
buf4 = malloc(sizeof(double[3][5]));
/* error checking */
but either way the trick comes at dereferencing time. You can't write buf[i][j] because buf has the wrong type. Nor can you use
double **hdl4 = (double**)buf;
hdl4[2][3] = 0; /* Wrong! */
because the compiler expects hdl4 to be the address of an address of a double. Nor can you use double incomplete_ary4[][]; because this is an error;
So what can you do?
Do the row and column arithmetic yourself
Allocate and do the work in a function
Use an array of pointers (the mechanism qrdl is talking about)
Do the math yourself
Simply compute memory offset to each element like this:
for (i=0; i<3; ++i){
for(j=0; j<3; ++j){
buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about
padding in this case */
}
}
Allocate and do the work in a function
Define a function that takes the needed size as an argument and proceed as normal
void dary(int x, int y){
double ary4[x][y];
ary4[2][3] = 5;
}
Of course, in this case ary4 is a local variable and you can not return it: all the work with the array must be done in the function you call of in functions that it calls.
An array of pointers
Consider this:
double **hdl5 = malloc(3*sizeof(double*));
/* Error checking */
for (i=0; i<3; ++i){
hdl5[i] = malloc(5*sizeof(double))
/* Error checking */
}
Now hdl5 points to an array of pointers each of which points to an array of doubles. The cool bit is that you can use the two-dimensional array notation to access this structure---hdl5[0][2] gets the middle element of the first row---but this is none-the-less a different kind of object than a two-dimensional array declared by double ary[3][5];.
This structure is more flexible then a two dimensional array (because the rows need not be the same length), but accessing it will generally be slower and it requires more memory (you need a place to hold the intermediate pointers).
Note that since I haven't setup any guards you'll have to keep track of the size of all the arrays yourself.
Arithmetic
c provides no support for vector, matrix or tensor math, you'll have to implement it yourself, or bring in a library.
Multiplication by a scaler and addition and subtraction of arrays of the same rank are easy: just loop over the elements and perform the operation as you go. Inner products are similarly straight forward.
Outer products mean more loops.
If you know the number of columns at compile time, it's pretty simple:
#define COLS ...
...
size_t rows;
// get number of rows
T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T
You can treat ap like any 2D array:
ap[i][j] = x;
When you're done you deallocate it as
free(ap);
If you don't know the number of columns at compile time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, it's still pretty simple:
size_t rows;
size_t cols;
// get rows and cols
T (*ap)[cols] = malloc(sizeof *ap * rows);
...
ap[i][j] = x;
...
free(ap);
If you don't know the number of columns at compile time and you're working with a version of C that doesn't support variable-length arrays, then you'll need to do something different. If you need all of the elements to be allocated in a contiguous chunk (like a regular array), then you can allocate the memory as a 1D array, and compute a 1D offset:
size_t rows, cols;
// get rows and columns
T *ap = malloc(sizeof *ap * rows * cols);
...
ap[i * rows + j] = x;
...
free(ap);
If you don't need the memory to be contiguous, you can follow a two-step allocation method:
size_t rows, cols;
// get rows and cols
T **ap = malloc(sizeof *ap * rows);
if (ap)
{
size_t i = 0;
for (i = 0; i < cols; i++)
{
ap[i] = malloc(sizeof *ap[i] * cols);
}
}
ap[i][j] = x;
Since allocation was a two-step process, deallocation also needs to be a two-step process:
for (i = 0; i < cols; i++)
free(ap[i]);
free(ap);
malloc will do.
int rows = 20;
int cols = 20;
int *array;
array = malloc(rows * cols * sizeof(int));
Refer the below article for help:-
http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf
Here is working code that defines a subroutine make_3d_array to allocate a multidimensional 3D array with N1, N2 and N3 elements in each dimension, and then populates it with random numbers. You can use the notation A[i][j][k] to access its elements.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Method to allocate a 2D array of floats
float*** make_3d_array(int nx, int ny, int nz) {
float*** arr;
int i,j;
arr = (float ***) malloc(nx*sizeof(float**));
for (i = 0; i < nx; i++) {
arr[i] = (float **) malloc(ny*sizeof(float*));
for(j = 0; j < ny; j++) {
arr[i][j] = (float *) malloc(nz * sizeof(float));
}
}
return arr;
}
int main(int argc, char *argv[])
{
int i, j, k;
size_t N1=10,N2=20,N3=5;
// allocates 3D array
float ***ran = make_3d_array(N1, N2, N3);
// initialize pseudo-random number generator
srand(time(NULL));
// populates the array with random numbers
for (i = 0; i < N1; i++){
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
ran[i][j][k] = ((float)rand()/(float)(RAND_MAX));
}
}
}
// prints values
for (i=0; i<N1; i++) {
for (j=0; j<N2; j++) {
for (k=0; k<N3; k++) {
printf("A[%d][%d][%d] = %f \n", i,j,k,ran[i][j][k]);
}
}
}
free(ran);
}
There's no way to allocate the whole thing in one go. Instead, create an array of pointers, then, for each pointer, create the memory for it. For example:
int** array;
array = (int**)malloc(sizeof(int*) * 50);
for(int i = 0; i < 50; i++)
array[i] = (int*)malloc(sizeof(int) * 50);
Of course, you can also declare the array as int* array[50] and skip the first malloc, but the second set is needed in order to dynamically allocate the required storage.
It is possible to hack a way to allocate it in a single step, but it would require a custom lookup function, but writing that in such a way that it will always work can be annoying. An example could be L(arr,x,y,max_x) arr[(y)*(max_x) + (x)], then malloc a block of 50*50 ints or whatever and access using that L macro, e.g.
#define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)]
int dim_x = 50;
int dim_y = 50;
int* array = malloc(dim_x*dim_y*sizeof(int));
int foo = L(array, 4, 6, dim_x);
But that's much nastier unless you know the effects of what you're doing with the preprocessor macro.
int rows, columns;
/* initialize rows and columns to the desired value */
arr = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
{
arr[i] = (int*)malloc(cols*sizeof(int));
}
// use new instead of malloc as using malloc leads to memory leaks
`enter code here
int **adj_list = new int*[rowsize];
for(int i = 0; i < rowsize; ++i)
{
adj_list[i] = new int[colsize];
}

Resources