How to allocate dynamic memory for 2d array in function ?
I tried this way:
int main()
{
int m=4,n=3;
int** arr;
allocate_mem(&arr,n,m);
}
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*arr[i]=(int*)malloc(m*sizeof(int));
}
But it doesn't work.
Your code is wrong at *arr[i]=(int*)malloc(m*sizeof(int)); because the precedence of the [] operator is higher than the * deference operator: In the expression *arr[i], first arr[i] is evaluated then * is applied. What you need is the reverse (dereference arr, then apply []).
Use parentheses like this: (*arr)[i] to override operator precedence. Now, your code should look like this:
void allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n*sizeof(int*));
for(int i=0; i<n; i++)
(*arr)[i] = (int*)malloc(m*sizeof(int));
}
To understand further what happens in the above code, read this answer.
It is important that you always deallocate dynamically allocated memory explicitly once you are done working with it. To free the memory allocated by the above function, you should do this:
void deallocate_mem(int*** arr, int n){
for (int i = 0; i < n; i++)
free((*arr)[i]);
free(*arr);
}
Additionally, a better way to create a 2D array is to allocate contiguous memory with a single malloc() function call as below:
int* allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n * sizeof(int*));
int *arr_data = malloc( n * m * sizeof(int));
for(int i=0; i<n; i++)
(*arr)[i] = arr_data + i * m ;
return arr_data; //free point
}
To deallocate this memory:
void deallocate_mem(int*** arr, int* arr_data){
free(arr_data);
free(*arr);
}
Notice that in the second technique malloc is called only two times, and so in the deallocation code free is called only two times instead of calling it in a loop. So this technique should be better.
Consider this: Just single allocation
int** allocate2D(int m, int n)
{
int **a = (int **)malloc(m * sizeof(int *) + (m * n * sizeof(int)));
int *mem = (int *)(a + m);
for(int i = 0; i < m; i++)
{
a[i] = mem + (i * n);
}
return a;
}
To Free:
free(a);
If your array does not need to be resized (well, you can, but il will be a bit more complicated), there is an easier/more efficient way to build 2D arrays in C.
Take a look at http://c-faq.com/aryptr/dynmuldimary.html.
The second method (for the array called array2) is quite simple, less painful (try to add the tests for mallocs' return value), and way more efficient.
I've just benchmarked it, for a 200x100 array, allocated and deallocated 100000 times:
Method 1 : 1.8s
Method 2 : 47ms
And the data in the array will be more contiguous, which may speed things up (you may get some more efficient techniques to copy, reset... an array allocated this way).
Rather allocating the memory in many different block, one can allocate this in a consecutive block of memory.
Do the following:
int** my2DAllocation(int rows,int columns)
{
int i;
int header= rows *sizeof(int *);
int data=rows*cols*sizeof(int);
int ** rowptr=(int **)malloc(header+data);
if(rowptr==NULL)
{
return NULL:
}
int * buf=(int*)(rowptr+rows);
for(i=0;i<rows;i++)
{
rowptr[i]=buf+i*cols;
}
return rowptr;
}
That is an unnecessarily complicated way of allocating space for an array. Consider this idiom:
int main(void) {
size_t m = 4, n = 3;
int (*array)[m];
array = malloc(n * sizeof *array);
free(array);
}
I have tried the following code for allocating memory to 2 dimensional array.
#include<stdio.h>
#include<malloc.h>
void main(void)
{
int **p;//double pointer holding a 2d array
int i,j;
for(i=0;i<3;i++)
{
p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
for(j=(3*i+1);j<(3*i+4);j++)
{
*p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
**p = j;
printf(" %d",**p);//print integers in a row
printf("\n");
p++;
}
}
}
Output of the above code is:-
1 2 3
4 5 6
7 8 9
In order to understand 2 dimensional array in terms of pointers, we need to understand how it will be allocated in memory, it should be something like this:-
1 2 3
1000 --> 100 104 108
4 5 6
1004 --> 200 204 208
7 8 9
1008 --> 300 304 308
from the above, we understand that, when we allocate memory to pointer p which is a double pointer, it is pointing to an array of integers, so in this example, we see that the 0x1000 is pointer p.
This pointer is pointing to integer pointer *p which is array of integers, when memory is allocated inside the inner for loop, during first iteration the pointer is 0x100 which is pointing to integer value 1, when we assign **p = j. Similarly it will be pointing to 2 and 3 in the next iterations in the loop.
Before the next iteration of the outer loop, double pointer is incremented, inside the next iteration, as is seen in this example the pointer is now at 0x1004 and is pointing to integer pointer which is an array of integers 4,5,6 and similarly for the next iterations in the loop.
Try the following code:
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*(arr+i)=(int*)malloc(m*sizeof(int));
}
2d Array dynamically array using malloc:
int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc
int **arrM = (int**)malloc (row*sizeof(int*));
for (int i=0;i<row;i++)
{
arrM[i] = (int*)malloc(column*sizeof(int));
// insert the value for each field
for (int j =0;j<column;j++,val++)
{
arrM[i][j] = val;
}
}
// De-allocation
for (int i=0;i<row;i++)
{
free(arrM[i]);
}
free(arrM);
arrM = 0;
//
// Now using New operator:
//
int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
arr[i] = new int[column];
// insert the value for each field
for (int j =0;j<column;j++,k++)
{
arr[i][j] = k;
}
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;
// Need to deallcate memory;
for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;
Related
I know there are very similar questions, but I've read them and I don't understand what is going wrong or what exactly I haven't understood about pointers to pointers.
My teacher is using a "learning by doing" approach to pointers and it has left me with approximately 100 questions. Sometimes I just change things around until it compiles, but it really isn't becoming any more clear to me, so if someone could help clarify a few things, I'd really appreciate it.
struct Matrix {
int rows; // number of rows
int cols; // number of columns
double **data;
};
typedef struct Matrix Matrix;
The pointer to a pointer, is something like this, right?
double *row1 = (double *) malloc (n_cols*sizeof(double));
double *row2 = (double *) malloc (n_cols*sizeof(double));
double *row3 = (double *) malloc (n_cols*sizeof(double));
double *data[] = { row1, row2, row3};
Data is pointing to the row number which is pointing to the doubles in the rows.
Now I am supposed to make a constructor function that makes a Matrix with a 0 in every position returns a pointer to a Matrix.
Matrix *make_matrix(int n_rows, int n_cols) {
Matrix *m = xmalloc(sizeof(Matrix));
m->rows = n_rows;
m->cols = n_cols;
double **rows_and_columns = xmalloc(n_rows * n_cols * sizeof(double));
memset(rows_and_columns, 0, m->rows * m->cols * sizeof(double));
m->data = *rows_and_columns;
return m;
}
So I made a pointer for the matrix, then I assigned the values for the rows and columns. Then I got confused (although I am not sure how confused, because this part compiles). I made a pointer to pointer for the last element of the struct Matrix (**data). Since **rows_and_columns has to hold the rows and columns, I allocated xmalloc(n_rows * n_cols * sizeof(double)) memory to it. I then set the whole thing to 0 and assign it to data. I think this m->data = rows_and_columns; says that m points to data and since data is a pointer and rows_and_columns is a pointer, we'll align their addresses, so m->data will also point to a bunch of 0s? Or is this wrong? And I am returning m, because the output is Matrix * and the m will get the * upon output, correct?
The next step is to copy a matrix, at which point I got even more lost.
Matrix *copy_matrix(double *data, int n_rows, int n_cols) {
Matrix *m = make_matrix(n_rows, n_cols);
double *row = (double *) malloc (n_cols*sizeof(double));
int i = 0;
for (int j = 0; j < n_rows; j++) {
for (; i < n_cols; i++) {
row = (double *) malloc (n_cols*sizeof(double));
row [i] = data[i + j*n_cols];
}
m->data [j] = *row [i];
}
free(row);
return m;
}
So we are returning a pointer to a Matrix again. The input is now a pointer to double values, which I am assuming are the rows. First, I made a matrix. Then I made a pointer for a row with a n columns worth of memory (double *) malloc (n_cols*sizeof(double)).
This is where I got super confused. I was imagining **data the whole time as something like above (double *data[] = { row1, row2, row3};). So, I wanted to copy each row of *data into *row, then save that as an entry in **data, like data[0] = row0, but something isn't clicking with the pointers, because I am not allowed to assign m->data [j] = row [i];, because I'm assigning incompatible types by assigning double * from type double?
xmalloc() returns a void * pointer to single block of memory.
What you need is one block of pointers, serving as an conceptual table header row, holding pointers to other memory blocks which themselves contain the actual doubles.
double **columns -> [double *col0] [double *col1] [double *col2] ...
| | |
V V V
[double col_val0] [double col_val0] ...
[double col_val1] [double col_val1]
[double col_val2] [double col_val2]
... ...
A matrix allocation could look like this:
// Allocate the double pointer array:
double **matrix_rows = xmalloc(sizeof(double *) * column_count);
// Iterate over each double-pointer in the double-pointer-array allocated above.
for(int i = 0; i < column_count; i++) {
// Allocate a new double-array, and let current double-pointer point to it:
matrix_rows[i] = malloc(sizeof(double) * row_count);
// Initialize matrix cell, iterating over allocated values.
for(int j = 0; j < row_count; j++) {
// Accessing the i'th col and j'th cell.
matrix_rows[i][j] = 0.0;
}
}
A possible implementation of a matrix copy function could be done by iteratively copying individial cells. One way to do this is using a loop composition.
for(int col = 0; col < col_count; col++) {
for(int row = 0; row < row_count; row++) {
destination_matrix[col][row] = source_matrix[col][row];
}
}
To give some intuition where an n-pointer indirection could be used:
n = 1: Strings, an array of characters.
n = 2: Paragraph, holding lines of strings.
n = 3: An article, holding a list of paragraphs.
Please be aware of using two indirections is usually not something you want. It is usually more efficient to store data in a linear fashion and compute linear indices out of two-compoment vectors and the other way around, especially in the case of this matrix example.
If you want to represent a matrix as an array of pointers to rows you need to allocate memory both for the rows and for the array of pointers to rows. It is simpler to allocate the rows consecutively as a single block.
typedef struct
{
int n_rows;
int n_cols;
double **rows;
double *data;
} Matrix;
Matrix *matrix_new (int n_rows, int n_cols)
{
// allocate matrix
Matrix *m = malloc (sizeof(Matrix));
m->n_rows = n_rows;
m->n_cols = n_cols;
// allocate m->data
m->data = malloc (n_rows * n_cols * sizeof(double));
// allocate and fill m->rows
m->rows = malloc (n_rows * sizeof(double*));
for (int i = 0; i < n_rows; i++) {
m->rows[i] = &data[i * n_cols];
}
// set the matrix to 0
for (int i = 0; i < n_rows; i++) {
for (int j = 0; j < n_cols; j++) {
m->rows[i][j] = 0.0;
}
}
return m;
}
The purpose of the rows array it to give you the convenience of being able to refer to element i,j with m->rows[i][j] instead of m->data[i * m->n_cols + j].
To free the matrix, take the inverse steps:
void matrix_free (Matrix *m)
{
free (m->rows);
free (m->data);
free (m);
}
To copy you can simply allocate a matrix of the same size and copy element by element:
Matrix *matrix_copy (Matrix *m1)
{
Matrix *m2 = matrix_new (m1->n_rows, m1->n_cols);
for (int i = 0; i < m1->n_rows; i++) {
for (int j = 0; j < m1->n_cols; j++) {
m2->rows[i][j] = m1->rows[i][j];
}
}
return m2;
}
The important thing to note is that you must not copy the rows array since it is unique to each matrix.
It is important to understand the difference between pointers-to-pointers and multi-dimensional arrays.
What makes it extra confusing is that the same syntax is used for referencing individual elements: var[i][j] will reference element (i,j) of var regardless of if var is a pointer to pointer, double **var or a two-dimensional array, double var[22][43].
What really happens is not the same. A two-dimensional array is a contiguous memory block. A pointer to pointers is an array of pointers that point to the individual rows.
// Two-dimensional array
char var1[X1][X2];
int distance = &var[4][7] - &var[0][0]; // distance = 4*X2+7
// Pointer-to-pointer
char **var2 = malloc(X1 * sizeof(char*)); // Allocate memory for the pointers
for (i=0; i<X1; i++) var2[i] = malloc(X2); // Allocate memory for the actual data
int distance2 = &var2[4][7] - &var[0][0]; // This could result in anything, since the different rows aren't necessarily stored one after another.
The calculation of distance2 invokes undefined behaviour since the C standard doesn't cover pointer arithmetic on pointers that point to different memory blocks.
You want to use pointer-to-pointer. So you need to first allocate memory for an array of pointers and then for each array:
Matrix *make_matrix(int n_rows, int n_cols) {
Matrix *m = xmalloc(sizeof(Matrix));
int i, j;
m->rows = n_rows;
m->cols = n_cols;
m->data = xmalloc(n_rows * sizeof(double*));
for (i=0; i < n_; i++) {
m->data[i] = xmalloc(n_cols * sizeof(double));
for (j=0; j < n_cols; j++) {
m->data[i][j] = 0.0;
}
}
return m;
}
Don't assume that the double 0.0 will have all bits set to 0!
To copy a matrix:
Matrix *copy_matrix(Matrix *source) {
Matrix *m = make_matrix(source->n_rows, source->n_cols);
int i, j;
for (j = 0; j < n_rows; j++) {
for (i = 0; i < n_cols; i++) {
m->data[i][j] = source[i][j];
}
}
return m;
}
I'll backup a bit and start with the basics. Pointers are one of those things that are not difficult to understand technically, but require you to beat your head into the I want to understand pointers wall enough for them to sink in. You understand that a normal variable (for lack of better words) is just a variable that holds a direct-reference to an immediate value in memory.
int a = 5;
Here, a is a label to the memory address that holds the value 5.
A pointer on the other hand, does not directly-reference an immediate value like 5. Instead a pointer holds, as its value, the memory address where 5 is stored. You can also think of the difference this way. A normal variable holds a value, while a pointer holds the address where the value can be found.
For example, to declare a pointer 'b' to the memory address holding 5 above, you would do something like:
int *b = &a;
or equivalently:
int *b = NULL;
b = &a;
Where b is assigned the address of a. To return the value stored at the address held by a pointer, or to operate directly on the value stored at the address held by a pointer, you must dereference the pointer. e.g.
int c = *b; /* c now equals 5 */
*b = 7; /* a - the value at the address pointed to by b, now equals 7 */
Now fast forward to pointer-to-pointer-to-type and simulated 2D matricies. When you declare your pointer-to-pointer-to-type (e.g. int **array = NULL), you are declaring a pointer that points to a pointer-to-type. To be useful in simlated 2D arrays (matricies, etc.), you must delcare an array of the pointer-to-pointer-to-type:
int **array = NULL;
...
array = calloc (NUM, sizeof *array); /* creates 'NUM' pointer-to-pointer-to-int. */
You now have NUM pointers to pointers-to-int that you can allocate memory to hold however many int values and you will assign the starting address for the memory block holding those int values to the pointers you previously allocated. For example, let's say you were to allocate space for an array of 5 random int values (from 1 - 1000) to each of the NUM pointers you allocated above:
for (i = 0; i < NUM; i++) {
array[i] = calloc (5, sizeof **array);
for (j = 0; j < 5; j++)
array[i][j] = rand() % 1000 + 1;
}
You have now assigned each of your NUM pointers (to-pointer-to-int) the starting address in memory where 5 random int values are stored. So your array is now complete. Each of your original NUM pointers-to-pointer-to-int now points to the address for a block of memory holding 5 int values. You can access each value with array notation (e.g. array[i][j] or with pointer notation *(*(array + i) + j) )
How do you free the memory? In the reverse order you allocated (values, then pointers):
for (i = 0; i < NUM; i++)
free (array[i]);
free (array);
Note: calloc both allocates memory and initializes the memory to 0/nul. This is particularly useful for both the pointers and arrays when dealing with numeric values, and when dealing with an unknown number of rows of values to read. Not only does it prevent an inadvertent read from an uninitialized value, but it also allows you to iterate over your array of pointers with i = 0; while (array[i] != NULL) {...}.
I want to create a dynamic array of void*s, each void* will point to 2d int matrix.
All of the matrices have the same number of rows and columns.
How to do this in C?
What do I do after I initialize: void **myArray = NULL;
More specifically, I want to create a function, that takes 2 parameters:
int foo( void* matrix, void** ptrArray)
Where matrix points to 2d int matrix, ptrArray points to an array of void*s, and foo returns the size of ptrArray.
I want, foo to get the 2d int matrix from matrix and make some manipulations on it, like switch some numbers in it. For every change that I make, I want to allocate a new matrix, and save a pointer to it in ptrArray.
Assuming that you allocate your void **twodarray somewhere else and you put NULL in the last+1 element of this array.
I think you want to do something like this;
int function(void **twodarray,void **ptrarray)
{
int i=0
for(i=0;twodarray[i]!=NULL;i++)/*repeat till twodarray points to NULL*/
{
perform some operation on twodarray[i];
ptrarray[i]=twodarray[i];
}
return i+1;/*return length of ptrarray */
}
This way you can tell the no of matrices there are.
But you will have to work out the allocation of void **twodarray by the methods explained in other replies.
You'll have to dynamically allocate each matrix.
For purposes of example I'm going to assume that you are creating your "2d int matrix" as a linear, 16 int array.
#define MATRIX_SIZE 16
int foo(void* matrix, void** ptrArray){
assert(ptrArray == NULL);
int result = 0;
int* first = malloc(MATRIX_SIZE * sizeof(int));
//do stuff to matrix
for(int i = 0; i < MATRIX_SIZE; ++i){
first[i] = matrix[i];
}
ptrArray = malloc((++result) * sizeof(void*));
ptrArray[0] = (void*)first;
int* second = malloc(MATRIX_SIZE * sizeof(int));
//do stuff to matrix
for(int i = 0; i < MATRIX_SIZE; ++i){
second[i] = matrix[i];
}
ptrArray = realloc((++result) * sizeof(void*));
ptrArray[1] = (void*)second;
.
.
.
return result;
}
I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.
I'm getting the double free or corruption error upon executing my code. Essentially, I am just creating a matrix in C (of any RxC dimension, which is why pointers are used), swapping two rows, printing the results, and then attempting to free the memory. When I do not swap the rows, the freeing works perfectly. When I do, it crashes. I've attempted to alter the way the swapping works to no avail. I think it has something to do with the temporary pointer for swapping going out of scope, but I'm not sure if this is the problem and how I would fix it.
MatElement is just a double.
typedef double MatElement;
main:
int main(int argc, char *argv[]) {
MatElement** matrix = matrixAlloc(3,3);
int i;
int j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++) {
matrix[i][j] = i+j;
}
}
matrixPrint(matrix, "%5.1f", 3, 3);
swapRows(matrix, 0, 2);
matrixPrint(matrix, "%5.1f", 3, 3);
matrixFree(matrix);
return 0;
}
The way the matrices are allocated:
MatElement **matrixAlloc(int nr, int nc) {
int i;
MatElement *ptr;
MatElement **A;
A = malloc(nr * sizeof(MatElement *)); /* array of ptrs */
ptr = calloc(nr * nc, sizeof(MatElement)); /* matrix elements */
for (i = 0; i < nr; i++) /* set row pointers properly */
A[i] = ptr + nc * i;
return A;
}
The way they are freed:
void matrixFree(MatElement **A) {
free(A[0]);
free(A);
}
The way their rows are swapped:
void swapRows(MatElement** G, int pivotRow, int rowExamined) {
MatElement* temp;
temp = G[rowExamined];
G[rowExamined] = G[pivotRow];
G[pivotRow] = temp;
}
Does anyone have any idea about what would be causing this double free() / invalid free()?
At some point, you are swapping the first row of the matrix into another position, so the free(A[0]) in matrixFree() is attempting to free a pointer into the middle of the array, instead of the pointer returned by calloc(). You will need to save that original pointer somewhere so that you can pass it, unmolested, to free().
Your matrix looks like this way :
A has all the pointers to the first element of all the rows. So initially, A[0] points to 0th row, A[1] to 1st row and so on.
So, when you are trying to free the matrix, you know that A[0] points to first row. But at that time you are assuming that your matrix elements are in continuous position and A[0] will always point to initial pointer returned by calloc. But when you swap some rows (specially the 0th with any of other row), then A[0] doesnt point to pointer returned by calloc.
possible solution involves like allocating one more memory slot in A like :
A = malloc( ((nr+1) * sizeof(MatElement )); / array of ptrs */
and then storing original pointer returned by calloc to A[nr].
So, A[nr] will also point to calloc returned pointer.
I have the following C code :
int *a;
size_t size = 2000*sizeof(int);
a = malloc(size);
which works fine. But if I have the following :
char **b = malloc(2000*sizeof *b);
where every element of b has different length.
How is it possible to do the same thing for b as i did for a; i.e. the following code would hold correct?
char *c;
size_t size = 2000*sizeof(char *);
c = malloc(size);
First, you need to allocate array of pointers like char **c = malloc( N * sizeof( char* )), then allocate each row with a separate call to malloc, probably in the loop:
/* N is the number of rows */
/* note: c is char** */
if (( c = malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }
for ( i = 0; i < N; i++ )
{
/* x_i here is the size of given row, no need to
* multiply by sizeof( char ), it's always 1
*/
if (( c[i] = malloc( x_i )) == NULL )
{ /* error */ }
/* probably init the row here */
}
/* access matrix elements: c[i] give you a pointer
* to the row array, c[i][j] indexes an element
*/
c[i][j] = 'a';
If you know the total number of elements (e.g. N*M) you can do this in a single allocation.
The typical form for dynamically allocating an NxM array of type T is
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * M);
}
}
If each element of the array has a different length, then replace M with the appropriate length for that element; for example
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * length_for_this_element);
}
}
Equivalent memory allocation for char a[10][20] would be as follows.
char **a;
a=malloc(10*sizeof(char *));
for(i=0;i<10;i++)
a[i]=malloc(20*sizeof(char));
I hope this looks simple to understand.
The other approach would be to allocate one contiguous chunk of memory comprising header block for pointers to rows as well as body block to store actual data in rows. Then just mark up memory by assigning addresses of memory in body to the pointers in header on per-row basis. It would look like follows:
int** 2dAlloc(int rows, int* columns) {
int header = rows * sizeof(int*);
int body = 0;
for(int i=0; i<rows; body+=columnSizes[i++]) {
}
body*=sizeof(int);
int** rowptr = (int**)malloc(header + body);
int* buf = (int*)(rowptr + rows);
rowptr[0] = buf;
int k;
for(k = 1; k < rows; ++k) {
rowptr[k] = rowptr[k-1] + columns[k-1];
}
return rowptr;
}
int main() {
// specifying column amount on per-row basis
int columns[] = {1,2,3};
int rows = sizeof(columns)/sizeof(int);
int** matrix = 2dAlloc(rows, &columns);
// using allocated array
for(int i = 0; i<rows; ++i) {
for(int j = 0; j<columns[i]; ++j) {
cout<<matrix[i][j]<<", ";
}
cout<<endl;
}
// now it is time to get rid of allocated
// memory in only one call to "free"
free matrix;
}
The advantage of this approach is elegant freeing of memory and ability to use array-like notation to access elements of the resulting 2D array.
If every element in b has different lengths, then you need to do something like:
int totalLength = 0;
for_every_element_in_b {
totalLength += length_of_this_b_in_bytes;
}
return malloc(totalLength);
I think a 2 step approach is best, because c 2-d arrays are just and array of arrays. The first step is to allocate a single array, then loop through it allocating arrays for each column as you go. This article gives good detail.
2-D Array Dynamic Memory Allocation
int **a,i;
// for any number of rows & columns this will work
a = malloc(rows*sizeof(int *));
for(i=0;i<rows;i++)
*(a+i) = malloc(cols*sizeof(int));
malloc does not allocate on specific boundaries, so it must be assumed that it allocates on a byte boundary.
The returned pointer can then not be used if converted to any other type, since accessing that pointer will probably produce a memory access violation by the CPU, and the application will be immediately shut down.