I am desperately trying to free a 2d int array and can't manage to do so.
I guess there's something wrong when i intialize the array?
Could you please help me out?
int rows = 2;
int cols = 3;
int *mfields = (int *) malloc(sizeof(int) * rows * cols);
int **matrix = (int **) malloc(sizeof(int *) * rows);
for (int i = 0; i < rows; i++) {
matrix[i] = mfields + i * cols;
for(int j=0; j<rows;j++) {
matrix[i][j] = (i+1)*(j+1);
}
}
for (int i = 0; i < rows; i++) {
free((matrix[i]));
}
free(matrix);
Thanks in advance,
Christian
Two chunks of memory are allocated:
int *mfields = (int *) malloc(sizeof(int) * rows * cols);
int **matrix = (int **) malloc(sizeof(int *) * rows);
and therefore two chunks of memory should be freed:
free(matrix);
free(mfields);
Freeing multiple chunks of memory, as this loop does:
for (int i = 0; i < rows; i++) {
free((matrix[i]));
is incorrect, as it passes addresses to free that were never returned from malloc.
Generally, it is not good to implement matrices as pointers-to-pointers. This prevents the processor from doing load prediction and impairs performance. If the C implementation(s) that will be used with the code support variable length arrays, then it is preferable to simply allocate one chunk of memory:
int (*matrix)[cols] = malloc(rows * sizeof *matrix);
If variable length array support is not available, then a program should allocate one chunk of memory and use manual calculations to address array elements. While this is may be more work for the programmer, it is better for performance:
int *matrix = malloc(rows * cols * sizeof *matrix);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i*cols + j] = (i+1) * (j+1);
Related
I am trying to solve a Leetcode problem in C.
https://leetcode.com/problems/pascals-triangle/description/
This is my solution to the problem.
I don't think there's an issue with the solution but dynamically allocating memory for a 2D array is getting very complex. Can someone please help me figure out how to correctly allocate memory dynamically to a 2D array. Updated the code based on BLUEPIXY suggestions, I still seem to be getting runtime error.
/**
* Return an array of arrays.
* The sizes of the arrays are returned as *columnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
*columnSizes =1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
columnSizes[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
columnSizes[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
numColumns++;
}
*(columnSizes+i) = numColumns-1;
}
return returnArray;
}
Problems of new version
(1)
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
should be
*columnSizes = malloc(numRows * sizeof(int));
(※ it is not necessary to cast from void * in C).
(2)
*columnSizes =1;//type of `*columnSizes` is `int *`
should be
**columnSizes = 1;//meant columnSizes[0] = 1; at caller side (main)
(3)
columnSizes[i][j] = returnArray[i-1][j];
...
columnSizes[i][j] = returnArray[i-1][j-1];
should be
returnArray[i][j] = returnArray[i-1][j];
...
returnArray[i][j] = returnArray[i-1][j-1];
because this is typo.
(4)
numColumns++; move to after for(j=0;j<numColumns;j++){ }
(5)
*(columnSizes+i) = numColumns-1;
should be
*(*columnSizes+i) = numColumns-1;//For reasons similar to (2)
The whole fix code:
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
*columnSizes = malloc(numRows * sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
**columnSizes = 1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
returnArray[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
returnArray[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
}
numColumns++;
*(*columnSizes+i) = numColumns-1;
}
return returnArray;
}
Just do this
int *arr = (int *)malloc(r * c * sizeof(int));
and access the elements like this
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count;
OR
If you have the pointer to the pointer, then you get get some help from this code
int main()
{
int i,j;
int **p;
(p)=(int**)malloc(5*sizeof(int*));
for(i=0;i<5;i++)
*(p+i)=(int*)malloc(4*sizeof(int));
for(i=0;i<5;i++)
for(j=0;j<4;j++)
p[i][j]=2;
for(i=0;i<5;i++)
for(j=0;j<4;j++)
printf("%d",p[i][j]);
}
If all you have to do for your programming exercise is print out the results, why bother with any storage at all? Just use the solution here.
How to efficiently calculate a row in pascal's triangle?
Regarding multi-dimensional arrays and C, there is no native support for such a thing. So you have to build your own using one or more 1-D blocks of storage and tricks to index into that storage.
The simplest thing, which #tanuj-yadav suggested works fine for most 2-d arrays is just allocate a nXm-length block of storage and do very simple index arithmetic arr[i*c+j].
The other common approach is arrays of arrays (aka ragged arrays). Which is just like a list of lists, and are naively done with a malloc on each row (or column).
I have this struct called Grid that holds a 2d array of strings. I'v been searching on how to free multidimensional arrays properly and can't seem to find the problem with this procedure as valgrind keeps detecting errors and leaked memory. Thanks in advance!
typedef struct Grid{
int N;
int M;
char ***adj;
}TGrid;
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i, j;
for(i = 0; i < Grid->N; i++){
for(j = 0; j < Grid->M; j++){
free(Grid->adj[i][j]);
}
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
The way you malloc memory is incorrect, proper ways should be:
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
return Grid;
}
Note that, Grid->adj[i][j] always points to array of 10 char, you can use this:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid{
int N;
int M;
char (**adj)[10];
}TGrid;
TGrid* emptyGrid(int N, int M){
int i;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char (*)[10]));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char[10]));
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i;
for(i = 0; i < Grid->N; i++){
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
int main() {
TGrid* t = emptyGrid(2,3);
freeGrid(t);
return 0;
}
However, since free receives a void* parameter, there must be something else in your code.
The general structure of your code is fine, but the types under sizeof are wrong. The general idiom for malloc-ing memory looks as follows
T *p = malloc(N * sizeof *p);
or, equivalently
T *p = malloc(N * sizeof(T));
Note that in the latter (type-based) variant there's one less asterisk under sizeof than there's is in the recipient pointer type.
That's exactly how it should be in your case as well
Grid->adj = malloc(N * sizeof(char **));
/* Since `Grid->adj` is `char ***`, you should have `char **` under `sizeof` */
...
Grid->adj[i] = malloc(M * sizeof(char *));
/* Since `Grid->adj[i]` is `char **`, you should have `char *` under `sizeof` */
...
Grid->adj[i][j] = malloc(10 * sizeof(char));
/* Since `Grid->adj[i][j]` is `char *`, you should have `char` under `sizeof` */
If that's not what you need, then there must be something wrong with your types. There's no way to say without knowing your intent.
(And I would suggest you use the first approach to specifying sizeof under malloc - use expressions, not types. That way you won't have to count asterisks.)
However, in real life this specific error would typically only result in over-allocated memory. No out-of-bound access or memory leaks should occur. If valgrind reports such errors, there must be something else at work here as well.
It's difficult to see where the problem is since you haven't posted the code that uses the functions.
I want to point out that the calls to malloc need to be changed.
You have:
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
Those calls need to be changed to:
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
You can avoid such errors by using a coding style as follows:
Grid->adj = malloc(N * sizeof(*(Grid->adj)));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(*(Grid->adj[i])));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(*(Grid->adj[i][j])));
}
}
A simpler case that uses the same style:
char* cp = malloc(10*sizeof(*cp));
You are not allocating arrays, you are allocating pointer-based look-up tables. The only reason for doing so is if you wish the individual dimensions to have different lengths (such as in an array of strings). If you don't need that, you should never use pointer-to-pointer tables since they are slow, error-prone and needlessly complex.
To allocate an actual 3D array, you would do like this:
char (*array)[Y][Z] = malloc ( sizeof(char[X][Y][Z] );
...
free(array);
To allocate an array of strings, you would do like this:
char** lookup = malloc ( sizeof( char*[N] ) );
for(size_t i=0; i<N; i++)
{
lookup[i] = ...; // assign pointers to strings
}
...
free(lookup);
As a rule of thumb, whenever your program contains more than two levels of indirection, the program design is most likely bad.
I am experimenting to set up two arrays, let's say array myflags_init and array tripleP; both arrays are two dimenstional, because tripleP is an array of pointers that point to the corresponding index in array myflags_init. Below is my code, and the compiling works fine. I would like to discuss whether this makes sense, as the syntax is a bit crazy to me (e.g. int **tripleP[2] for declaring the two-dimenstional array tripleP of int pointers).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int m;
for (m = 0; m < 20; m++)
{
int *myflags_init[2];
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
int r, k;
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
myflags_init[r][k] = 0; /* initialize the two-d array to 0 */
}
}
int false_num = 0;
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
tripleP[r][k] = &myflags_init[r][k]; /* tripleP pointers point to the corresponding index in myflags_init */
}
}
}
return 0;
}
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
That works, but shouldn't be written like this. You want to allocate an array of int*, not int**. However it just so happens that both types have the same size (they are both pointers) and thus this will work anyway. But for clarity replace it with this:
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int *));
tripleP[1] = (int **) calloc(10, sizeof(int *));
Also the initialization of myflags_init[0] and myflags_init[1] is wrong, because you allocated for 2 elements for each, but try to initialize 10 of them:
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
//...
for (k = 0; k < 10; k++)
Also you don't need to set them manually to zero. That is exactly what calloc already does for you (in contrast to malloc).
And the outer for-loop seems rather pointless, not to mention the memory leak, because you keep allocating new memory but never call free.
If I allocate a 2D array like this int a[N][N]; it will allocate a contiguous block of memory.
But if I try to do it dynamically like this :
int **a = malloc(rows * sizeof(int*));
for(int i = 0; i < rows; i++)
a[i] = malloc(cols * sizeof(int));
This maintains a unit stride between the elements in the rows, but this may not be the case between rows.
One solution is to convert from 2D to 1D, besides that, is there another way to do it?
If your array dimensions are known at compile time:
#define ROWS ...
#define COLS ...
int (*arr)[COLS] = malloc(sizeof *arr * ROWS);
if (arr)
{
// do stuff with arr[i][j]
free(arr);
}
If your array dimensions are not known at compile time, and you are using a C99 compiler or a C2011 compiler that supports variable length arrays:
size_t rows, cols;
// assign rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
// do stuff with arr[i][j]
free(arr);
}
If your array dimensions are not known at compile time, and you are not using a C99 compiler or a C2011 compiler that supports variable-length arrays:
size_t rows, cols;
// assign rows and cols
int *arr = malloc(sizeof *arr * rows * cols);
{
// do stuff with arr[i * rows + j]
free(arr);
}
In fact, n-dimensional arrays (allocated on the stack) are really just 1-dimension vectors. The multiple indexing is just syntactic sugar. But you can write an accessor function to emulate something like what you want:
int index_array(int *arr, size_t width, int x, int y)
{
return arr[x * width + y];
}
const size_t width = 3;
const size_t height = 2;
int *arr = malloc(width * height * sizeof(*arr));
// ... fill it with values, then access it:
int arr_1_1 = index_array(arr, width, 1, 1);
However, if you have C99 support, then declaring a pointer to an array is possible, and you can even use the syntactic sugar:
int (*arr)[width] = malloc(sizeof((*arr) * height);
arr[x][y] = 42;
Say you want to dynamically allocate a 2-dimensional integer array of ROWS rows and COLS columns. Then you can first allocate a continuous chunk of ROWS * COLS integers and then manually split it into ROWS rows. Without syntactic sugar, this reads
int *mem = malloc(ROWS * COLS * sizeof(int));
int **A = malloc(ROWS * sizeof(int*));
for(int i = 0; i < ROWS; i++)
A[i] = mem + COLS*i;
// use A[i][j]
and can be done more efficiently by avoiding the multiplication,
int *mem = malloc(ROWS * COLS * sizeof(int));
int **A = malloc(ROWS * sizeof(int*));
A[0] = mem;
for(int i = 1; i < ROWS; i++)
A[i] = A[i-1] + COLS;
// use A[i][j]
Finally, one could give up the extra pointer altogether,
int **A = malloc(ROWS * sizeof(int*));
A[0] = malloc(ROWS * COLS * sizeof(int));
for(int i = 1; i < ROWS; i++)
A[i] = A[i-1] + COLS;
// use A[i][j]
but there's an important GOTCHA! You would have to be careful to first deallocate A[0] and then A,
free(A[0]);
free(A); // if this were done first, then A[0] would be invalidated
The same idea can be extended to 3- or higher-dimensional arrays, although the code will get messy.
You can treat dynamically allocated memory as an array of a any dimension by accessing it in strides:
int * a = malloc(sizeof(int) * N1 * N2 * N3); // think "int[N1][N2][N3]"
a[i * N2 * N3 + j * N3 + k] = 10; // like "a[i, j, k]"
The best way is to allocate a pointer to an array,
int (*a)[cols] = malloc(rows * sizeof *a);
if (a == NULL) {
// alloc failure, handle or exit
}
for(int i = 0; i < rows; ++i) {
for(int j = 0; j < cols; ++j) {
a[i][j] = i+j;
}
}
If the compiler doesn't support variable length arrays, that only works if cols is a constant expression (but then you should upgrade your compiler anyway).
Excuse my lack of formatting or any mistakes, but this is from a cellphone.
I also encountered strides where I tried to use fwrite() to output using the int** variable as the src address.
One solution was to make use of two malloc() invocations:
#define HEIGHT 16
#define WIDTH 16
.
.
.
//allocate
int **data = malloc(HEIGHT * sizeof(int **));
int *realdata = malloc(HEIGHT * WIDTH * sizeof(int));
//manually index
for (int i = 0; i < HEIGHT; i++)
data[i] = &realdata[i * WIDTH];
//populate
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
for (int j = 0; j < WIDTH; j++)
data[i][j] = idx++;
//select
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
printf("%i, ", data[i][j]);
printf("/n");
}
//deallocate
.
.
.
You can typedef your array (for less headake) and then do something like that:
#include <stdlib.h>
#define N 10
typedef int A[N][N];
int main () {
A a; // on the stack
a[0][0]=1;
A *b=(A*)malloc (sizeof(A)); // on the heap
(*b)[0][0]=1;
}
I have been asked in an interview how do i allocate a 2-D array and below was my solution to it.
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
I thought I had done a good job but then he asked me to do it using one malloc() statement not two. I don't have any idea how to achieve it.
Can anyone suggest me some idea to do it in single malloc()?
Just compute the total amount of memory needed for both nrows row-pointers, and the actual data, add it all up, and do a single call:
int **array = malloc(nrows * sizeof *array + (nrows * (ncolumns * sizeof **array));
If you think this looks too complex, you can split it up and make it a bit self-documenting by naming the different terms of the size expression:
int **array; /* Declare this first so we can use it with sizeof. */
const size_t row_pointers_bytes = nrows * sizeof *array;
const size_t row_elements_bytes = ncolumns * sizeof **array;
array = malloc(row_pointers_bytes + nrows * row_elements_bytes);
You then need to go through and initialize the row pointers so that each row's pointer points at the first element for that particular row:
size_t i;
int * const data = array + nrows;
for(i = 0; i < nrows; i++)
array[i] = data + i * ncolumns;
Note that the resulting structure is subtly different from what you get if you do e.g. int array[nrows][ncolumns], because we have explicit row pointers, meaning that for an array allocated like this, there's no real requirement that all rows have the same number of columns.
It also means that an access like array[2][3] does something distinct from a similar-looking access into an actual 2d array. In this case, the innermost access happens first, and array[2] reads out a pointer from the 3rd element in array. That pointer is then treatet as the base of a (column) array, into which we index to get the fourth element.
In contrast, for something like
int array2[4][3];
which is a "packed" proper 2d array taking up just 12 integers' worth of space, an access like array[3][2] simply breaks down to adding an offset to the base address to get at the element.
int **array = malloc (nrows * sizeof(int *) + (nrows * (ncolumns * sizeof(int)));
This works because in C, arrays are just all the elements one after another as a bunch of bytes. There is no metadata or anything. malloc() does not know whether it is allocating for use as chars, ints or lines in an array.
Then, you have to initialize:
int *offs = &array[nrows]; /* same as int *offs = array + nrows; */
for (i = 0; i < nrows; i++, offs += ncolumns) {
array[i] = offs;
}
Here's another approach.
If you know the number of columns at compile time, you can do something like this:
#define COLS ... // integer value > 0
...
size_t rows;
int (*arr)[COLS];
... // get number of rows
arr = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < COLS; j++)
arr[i][j] = ...;
}
If you're working in C99, you can use a pointer to a VLA:
size_t rows, cols;
... // get rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
arr[i][j] = ...;
}
How do we allocate a 2-D array using One malloc statement (?)
No answers, so far, allocate memory for a true 2D array.
int **array is a pointer to pointer to int. array is not a pointer to a 2D array.
int a[2][3] is an example of a true 2D array or array 2 of array 3 of int
To allocate memory for a true 2D array, with C99, use malloc() and save to a pointer to a variable-length array (VLA)
// Simply allocate and initialize in one line of code
int (*c)[nrows][ncolumns] = malloc(sizeof *c);
if (c == NULL) {
fprintf(stderr, "out of memory\n");
return;
}
// Use c
(*c)[1][2] = rand();
...
free(c);
Without VLA support, if the dimensions are constants, code can use
#define NROW 4
#define NCOL 5
int (*d)[NROW][NCOL] = malloc(sizeof *d);
You should be able to do this with (bit ugly with all the casting though):
int** array;
size_t pitch, ptrs, i;
char* base;
pitch = rows * sizeof(int);
ptrs = sizeof(int*) * rows;
array = (int**)malloc((columns * pitch) + ptrs);
base = (char*)array + ptrs;
for(i = 0; i < rows; i++)
{
array[i] = (int*)(base + (pitch * i));
}
I'm not a fan of this "array of pointers to array" to solve the multi dimension array paradigm. Always favored a single dimension array, at access the element with array[ row * cols + col]? No problems encapsulating everything in a class, and implementing a 'at' method.
If you insist on accessing the members of the array with this notation: Matrix[i][j], you can do a little C++ magic. #John solution tries to do it this way, but he requires the number of column to be known at compile time. With some C++ and overriding the operator[], you can get this completely:
class Row
{
private:
int* _p;
public:
Row( int* p ) { _p = p; }
int& operator[](int col) { return _p[col]; }
};
class Matrix
{
private:
int* _p;
int _cols;
public:
Matrix( int rows, int cols ) { _cols=cols; _p = (int*)malloc(rows*cols ); }
Row operator[](int row) { return _p + row*_cols; }
};
So now, you can use the Matrix object, for example to create a multiplication table:
Matrix mtrx(rows, cols);
for( i=0; i<rows; ++i ) {
for( j=0; j<rows; ++j ) {
mtrx[i][j] = i*j;
}
}
You should now that the optimizer is doing the right thing and there is no call function or any other kind of overhead. No constructor is called. As long as you don't move the Matrix between function, even the _cols variable isn't created. The statement mtrx[i][j] basically does mtrx[i*cols+j].
It can be done as follows:
#define NUM_ROWS 10
#define NUM_COLS 10
int main(int argc, char **argv)
{
char (*p)[NUM_COLS] = NULL;
p = malloc(NUM_ROWS * NUM_COLS);
memset(p, 81, NUM_ROWS * NUM_COLS);
p[2][3] = 'a';
for (int i = 0; i < NUM_ROWS; i++) {
for (int j = 0; j < NUM_COLS; j++) {
printf("%c\t", p[i][j]);
}
printf("\n");
}
} // end of main
You can allocate (row*column) * sizeof(int) bytes of memory using malloc.
Here is a code snippet to demonstrate.
int row = 3, col = 4;
int *arr = (int *)malloc(row * col * sizeof(int));
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*col + j) = ++count; //row major memory layout
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d ", *(arr + i*col + j));