Malloc a 2D array in C [duplicate] - arrays

This question already has answers here:
A different way to malloc a 2D array?
(3 answers)
Freaky way of allocating two-dimensional array?
(3 answers)
Closed 6 years ago.
Every time I allocate the memory for a 2D array first I create an array of int** and then with a for I allocate the memory for each element.
For example:
int ** arr = malloc(N*sizeof(int *));
for(i=0; i< N; i++) arr[i] = malloc(M*sizeof(int));
Wouldn't be possible allocate the memory like:
int ** arr = malloc(N*sizeof(int[M]));
or
int ** arr = malloc(sizeof(int[N][M]));
in order to avoid the for?

like this : int (*arr)[M] = malloc(sizeof(int[N][M]));
arr is pointer to int[M].
use like arr[0][M-1];
and free(arr);

int ** arr = malloc(N*sizeof(int[M]));
is incorrect C code, if you simulate it by allocating once
int *arr = malloc(N*M*sizeof(int));
and access it by
arr[i*M + j],
this is an analog to arr[I][j] in your first case.

You have a "pointer to pointer". That cannot represent a 2D array.
The correct declaration of a pointer to a 2D array is
// number of elements in one row
#define COLS 10
// number of rows
#define ROWS 20
int (*array)[COLS]; // mind the parenthesis!
That makes array a pointer to array of COLS ints. The type is `int (*)[COLS], btw. but you don't need the type, see below.
To allocate the array you should then use the standard allocation for a 1D array:
array = malloc(sizeof(*array) * ROWS); // COLS is in the `sizeof`
array = malloc(sizeof(int[ROWS][COLS])); // explicit 2D array notation
Which variant to use is personal style. While the first contains no redundancy (consider you change the declaration of array to use INNER instead of COLS or the element-type to float). The second is more clear at a fist glance, but more prone to errors when modifying the declaration of array.
To free:
free(array);

Related

Using pointer of pointer to reference a matrix [duplicate]

This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 3 years ago.
I am very new to C, and I am trying to get a int **data to represent a matrix of integers.
I first created an array of arrays, then I tried referencing the pointer of pointer to that array like so:
int **pointer;
int data[num_rows][num_cols];
pointer = (int**) data[0];
However I get a warning: cast to pointer from integer of a different size.
Can someone please help me understand what is going on, and how can I assign an array to int **pointer? (I have to use the double pointer)
The line int data[num_rows][num_cols]; does not actually declare an "array of arrays!" Rather, it declares a single array with two dimensions - in memory, this will be a single block of data, of size num_rows x num_cols x sizeof(int).
To get an "array of arrays" that you can access using a 'double pointer', you generally have to use the malloc function. Something like the following:
int **pointer = malloc(num_rows * sizeof(int*)); // allocate an array of pointers
for (int i = 0; i < num_rows; ++i) {
pointer[i] = malloc(num_cols * sizeof(int)); // allocate each row array
}
You can then access any [row][column] element via the double pointer:
pointer[row][column] = 1234;
When you've finished with the array(s), be sure to free the memory, like this:
for (int i = 0; i < num_cols; ++i) {
free(pointer[i]); // free each row array
}
free(pointer); // free the array of arrays
Alternatively, given your int data[num_rows][num_cols]; you could avoid the malloc calls inside the for loop, as follows:
int **pointer = malloc(num_rows * sizeof(int*)); // allocate an array of pointers
for (int i = 0; i < num_rows; ++i) {
pointer[i] = &data[i][0]; // Assign a pointer to the beginning of each row
}
Feel free to ask for further clarification and/or explanation.

C - multidimensional array memory allocation based on user input

I have seen the following declaration of two dimensional array.
int arr[][3] = { {1,2,3}, {4,5,6}};
My question is how can I allocate following multidimensional array in run time based on user input of first dimension?
#define M 10
#define N 15
int arr[][M][N]
Start by declaring a pointer suitable for accessing the array:
int (*array)[M][N];
Then allocate memory for the array based on the user input:
array = malloc(P * sizeof(*array)); // P is the value obtained from the user
Then use the pointer as if it was a 3D array:
array[x][y][z] = 42;
Don't forget to free the memory when you're done with it.
C allows variable-length arrays. So after reading the first dimension from the user, you can declare the array with that size.
int n;
printf("How big is it? ");
scanf("%d", &n);
int arr[n][M][N];

how to return the 2D array to the main() [duplicate]

This question already has answers here:
Return a 2d array from a function
(10 answers)
Return a 2d array from a function
(3 answers)
Closed 5 years ago.
I am learning c language and always confused with the array return using pointers.My question is:
I want to read and declare the 2D array inside
int ** readMatrix(int rows,int cols); function
and return it to the main()
plz give me the solution in simple language because I was already go through many books but couldn't understand.
thank you
To initialize memory for an 2D array within in another function with the intent to use the very same memory outside this function you must use malloc to ask for the required memory from the OS.
Malloc returns an void pointer to the start adress of the block of memory you requested or NULL if the request could not be served from the OS, which nowadays with home PC's is very unlikely to happen because it means you have run out of memory. malloc doc
If you want to create array of pointer of type Int you have to do the following
see
int ** readMatrix(int rows,int cols){
int** var = (int**) malloc(sizeof(int)*rows); //Here you allocate the memory for the pointer which will later point the the columns
for (int i=0; i<r; i++)
arr[i] = (int *)malloc(cols * sizeof(int)); //Here you allocate the columns
return var;
}
another way would be to map an 2D array onto an 1D array. What do I mean with mapping? Let me show it with an example:
If you want to map all Elements from an 2D array onto 1D array the 1D array must have the same number of Elements as the 2D array otherwise you would miss elements.
Then you need some kind of formula to calc the index from 2D array to an 1D array. The formula is: y*width+x
Width represent the maximum amount of elements one row of the 2D array can contain. X represent your position on the current row and Y represent the row you are currently at.
in C it would look like this:
int* var = malloc(sizeof(int)*rows*cols);
for(int i = 0; i < row; i++)
for(int j = 0; j < cols; j++)
var[i*cols+j] = 0;

Allocating 2-D array in C

I want to allocate a 2-D array in C at runtime. Now this can be achieved in the conventional manner like this:
int *matrix[rows]
for (row = 0; row < rows; ++row) {
matrix[row] = (int *)malloc(ncol*sizeof(int));
}
But I found another method, which does the same thing:
int (*p)[rows];
p=(int (*)[rows])malloc(rows*cols*sizeof(int));
Can anyone explain how the 2nd declaration works? Specifically, what is meant by (int (*)[rows])malloc? To the best of my knowledge, malloc is used like (int *)malloc(ncol*sizeof(int)) or (char *)malloc(ncol*sizeof(char)).
Here, you cast malloc's return value to the type pointer to array rows of int.
By the way, in C, the cast of a pointer to void to a pointer to object is not requiered, and even useless. You should not worry about these details. The following code works indeed as well.
#include <stdlib.h>
int (*p)[rows];
p = malloc(rows * cols * sizeof(int));
These are not equivalent, the first allocates an array of pointers to integers, the second allocates an array of integers and returns a pointer to it, you just allocate several next to each other therefore allowing a second dimension to the 'array'.
A simpler version if you don't need the array after the end of the function would be:
int matrix[rows][cols];

Can anyone help me debug this 2D array?

I am trying to increase the size of my 2D array and hm is a struct that contains the x length of the array. I am using value -99999991 to indicate the end of the array.
Is this the correct way to do it?
hm->value = realloc(hm->value,(hm->x+1)*sizeof(int));
hm->value[hm->x] = malloc(sizeof(int));
hm->value[hm->x][0] = -999999991;
hm->value[hm->x-1] = realloc(hm->value[hm->x-1],2*sizeof(int));
hm->value[hm->x-1][1] = -999999991;
hm->value[hm->x-1][0] = value;
You don't have a 2D array if it can be resized, you have a pointer to a pointer to an int.
An array:
int A[n][m];
Accessing the array: A[2][3] = 4; // Equivalent to *(A + 2*m + 3)
A variable sized 2D "array":
int **A;
A = malloc(n*m*sizeof(int));
A[2][3] = 4; // Equivalent to *A + 2*??? + 3)
The compiler doesn't know if your array is one dimensional, or if it is two dimensional then what the size of the two dimensions are. It can't calculate this any more.
Also, realloc can't put the data in the right place. Consider a 2x2 2D array going to a 2x3 2D array:
int **A = {{0,1}, {2,3}}; // for berevity - this isn't valid C!
// stored in memory as [0,1,2,3]
A = realloc(A, 2*3* sizeof(int));
New array stored in memory is [0,1, , 2, 3, ]; This required copying the data.
There are two decent solutions (though they aren't pretty):
1) Treat your 2D array as a list of 1D arrays
int **A;
A = malloc(m*sizeof(void *));
for (i = 0; i < m; ++i) {
A[i] = malloc (n*sizeof(int);
}
(now realloc should work on both of these arrays, but accessing elements will require two pointer dereferences rather than pointer arithmetic)
2) if one of the dimensions of the array is fixed then we can use a 2D array in memory and realloc it as required.
#define M 16
int **A;
A = malloc(M*n*sizeof(int)); // realloc also works
// access an element:
*(A + 3*M + 2) = 4; // (3*M is compile time constant)
In this second example we always grow at the end of our 2D array (so my example of going from 2x2 to 2x3 is illegal - the second 2 is a fixed length).

Resources