i want to allocate a matrix.
is this the only option:
int** mat = (int**)malloc(rows * sizeof(int*))
for (int index=0;index<row;++index)
{
mat[index] = (int*)malloc(col * sizeof(int));
}
Well, you didn't give us a complete implementation. I assume that you meant.
int **mat = (int **)malloc(rows * sizeof(int*));
for(int i = 0; i < rows; i++) mat[i] = (int *)malloc(cols * sizeof(int));
Here's another option:
int *mat = (int *)malloc(rows * cols * sizeof(int));
Then, you simulate the matrix using
int offset = i * cols + j;
// now mat[offset] corresponds to m(i, j)
for row-major ordering and
int offset = i + rows * j;
// not mat[offset] corresponds to m(i, j)
for column-major ordering.
One of these two options is actually the preferred way of handling a matrix in C. This is because now the matrix will be stored contiguously in memory and you benefit from locality of reference. Basically, the CPU cache will a lot happier with you.
The other answers already covered these, but for completeness, the comp.lang.c FAQ has a relevant entry:
How can I dynamically allocate a multidimensional array?
what you can do is
int (*mat)[col];
mat=(int (*)[col])malloc(sizeof(*mat)*row);
and then use this new matrix as mat[i][j]
You may also use calloc, which will additionally zero initialize the matrix for you. The signature is slightly different:
int *mat = (int *)calloc(rows * cols, sizeof(int));
How about just:
int* mat = malloc(rows * columns * sizeof(int));
You can collapse it to one call to malloc, but if you want to use a 2d array style, you still need the for loop.
int** matrix = (int*)malloc(rows * cols * sizeof(int) + rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
matrix[i] = matrix + rows * sizeof(int*) + rows * cols * sizeof(int) * i;
}
Untested, but you get the idea. Otherwise, I'd stick with what Jason suggests.
Related
Can I use
size_t m, n;
scanf ("%zu%zu", &m, &n);
int (*a)[n] = (int (*)[n])calloc (m * n, sizeof (int));
to create a dynamic 2D array in C, whose size of rows and columns can be modified by function realloc during runtime?
Also you can use pointer-to-pointer-to-int and alloc first array for "pointers to lines" and then init all items by allocating memory for "arrays of int".
Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
size_t m, n;
scanf("%zu%zu", &m, &n);
int **a = (int **)calloc(m, sizeof(int*));
size_t i, j;
for (i = 0; i < m; i++) {
a[i] = (int *)calloc(n, sizeof(int));
}
/// Work with array
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
a[i][j] = i+j;
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
Such approach allows to make realloc later
This record
int (*a)[n] = (int (*)[n])calloc (m * n, sizeof (int));
is correct provided that the compiler supports variable length arrays.
It may be written also like
int (*a)[n] = calloc ( 1, sizeof ( int[m][n] ) );
On the other hand, there is a problem when you will use realloc and the number of columns must be changed. This can result in losing elements in the array in its last row because C memory management functions know nothing about types of objects for which the memory is allocated. They just allocate extents of memory of required sizes.
Otherwise if the compiler does not support variable length arrays you will need to allocate array of pointers and for each pointer an array of integers. This approach is more flexible in sense that you can reallocate separately columns and rows.
Can I create a dynamic 2D array in C like this?
int (*a)[n] = (int (*)[n])calloc (m * n, sizeof (int));
Yes.
Cleaner as int (*a)[n] = calloc(m, sizeof a[0]);
Can I use int (*a)[n] = .... to create a dynamic 2D array in C, whose size of rows and columns can be modified by function realloc during runtime?
No. Once an array size of a is defined, (n in this case), the size can not change.
Instead consider allocating an array of arrays
// Error checking omitted for brevity
int **a2 = malloc(sizeof a2 * rows);
for (r = 0; r < rows; r++) {
a2[r] = malloc(sizeof a2[0] * cols);
}
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);
Kindly, can someone explain to me the difference between the following two declarations of n*n Matrix.
int **Matrix;
Matrix = malloc(n * sizeof(int *));
for (i = 0; i < n; i++)
{
Matrix[i] = malloc(n * sizeof(int));
}
and
Matrix = malloc(n * sizeof(int)); // without pointer
for (i = 0; i < n; i++)
{
Matrix[i] = malloc(n * sizeof(int));
}
Thank you.
The second one is wrong because you are allocating space for ints and not for pointers, on a 64bit system (or where sizeof(int) < sizeof(void *)) it will cause undefined behavior because the code will access memory beyond that allocated with malloc().
Perhaps what you saw was
int *matrix;
matrix = malloc(n * n * sizeof(*matrix));
if (matrix == NULL)
abort_malloc_failed();
which allocates a n×n "matrix" of contiguos integers, you cannot access this with two index notation however.
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));