Understanding the difference methods of malloc - c

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.

Related

Problems when freeing a dynamically allocated 2d array in C

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);

Dynamically allocating memory for array's elements

I have a two-dimension array of custom data type, say something like
struct element_t ** arr
How do I allocate space for this array's single elements (arr[i][j] ) using malloc()? Thanks in advance.
You can do the following :
struct element_t **arr;
arr = malloc(N * sizeof(*arr));
for (int i = 0; i < N; ++i) {
arr[i] = malloc(X * sizeof(*arr[i]));
}
Where N is the size of your double array and X the size of each array;
It depends how you want to allocate memory. If you want a contiguous chunk of memory then
arr = malloc(nrows * sizeof(*arr));
arr[0] = malloc(nrows * ncolumns * sizeof(struct element_t));
for(int i = 1; i < nrows; i++)
arr[i] = arr[0] + i * ncolumns;
For non contiguous
arr = malloc(nrows * sizeof(*arr));
for(int i = 0; i < nrows; i++)
arr[i] = malloc(ncolumns * sizeof(struct element_t));
For detailed explanation read How can I dynamically allocate a multidimensional array?

Dynamic memory allocation - 2 dimensional array

I have some troubles understanding pointers and dynamic memory allocation. I wrote those 2 codes:
int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
{
fprintf(stderr, "out of memory\n");
return -1;
}
for(i = 0; i < nrows; i++)
{
*(array+i) = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
return -1;
}
}
and:
int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
{
fprintf(stderr, "out of memory\n");
return -1;
}
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
return -1;
}
}
They should allocate space for 2 dimensional array. Although Im not sure if theyre both correct, I mean: does this line:
array[i] = malloc(ncolumns * sizeof(int));
do the exact same thing line this one:
*(array+i) = malloc(ncolumns * sizeof(int));
?
Yes.
array[i], *(array+i) and i[array] are treated as same things by the compiler.
Both *(array + i) and array[i] evaluate to the same thing (assuming that one is a pointer and the other an integer). For your sanity and everyone else's, use the second form; it'll be easier to read and maintain.
If you know the size of your array dimensions at compile time, or if you are working with a compiler that supports variable-length arrays, you can simplify this a bit:
int (*array)[ncols] = malloc( sizeof *array * nrows );
This will allocate enough memory for an nrows x ncols array of int. If you're working with a compiler that does not support variable-length arrays, then ncols must be known at compile time (i.e., it must be a macro or other compile-time constant). You would access array elements as you would for any regular 2D array:
array[i][j] = x;
One advantage this method has over the two-step method is that all the memory is allocated contiguously; that is, all the rows will be adjacent in memory. This can matter if you want to treat the array as a single continuous blob of data (such as if you're sending it over a socket via a write system call). With the two-step method, it's not guaranteed that all the rows will be adjacent.
The other advantage is that deallocation only requires a single call to free:
free( array );
Yes, they should all be treated the same when you compile your code.
int **array;
array = malloc(nrows * sizeof(int *));
the variable array is an array of pointer or double pointer variable. the value of these pointers are done in the next array allocation :
array[i] = malloc(ncolumns * sizeof(int)); or
*(array+i) = malloc(ncolumns * sizeof(int));
array [i]==> i is the index of array witch contain the value of pointer allocated by malloc(ncolumns * sizeof(int));
*(array + i) ==> is the offset using to parse array and *array + i) is the value of pointer allocated by malloc(ncolumns * sizeof(int));
so
array[i] = malloc(ncolumns * sizeof(int));
and
*(array+i) = malloc(ncolumns * sizeof(int));
are exactly the same

Dynamic memory allocation for 3D array [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Malloc a 3-Dimensional array in C?
dynamic allocation/deallocation of 2D & 3D arrays
How can i allocate 3D arrays using malloc?
There are two different ways to allocate a 3D array. You can allocate it either as a 1D array of pointers to a (1D array of pointers to a 1D array). This can be done as follows:
int dim1, dim2, dim3;
int i,j,k;
double *** array = (double ***)malloc(dim1*sizeof(double**));
for (i = 0; i< dim1; i++) {
array[i] = (double **) malloc(dim2*sizeof(double *));
for (j = 0; j < dim2; j++) {
array[i][j] = (double *)malloc(dim3*sizeof(double));
}
}
Sometimes it is more appropriate to allocate the array as a contiguous chunk. You'll find that many existing libraries might require the array to exist in allocated memory. The disadvantage of this is that if your array is very very big you might not have such a large contiguous chunk available in memory.
const int dim1, dim2, dim3; /* Global variables, dimension*/
#define ARR(i,j,k) (array[dim2*dim3*i + dim3*j + k])
double * array = (double *)malloc(dim1*dim2*dim3*sizeof(double));
To access your array you just use the macro:
ARR(1,0,3) = 4;
This would work
int main()
{
int ***p,i,j;
p=(int ***) malloc(MAXX * sizeof(int **));
for(i=0;i<MAXX;i++)
{
p[i]=(int **)malloc(MAXY * sizeof(int *));
for(j=0;j<MAXY;j++)
p[i][j]=(int *)malloc(MAXZ * sizeof(int));
}
for(k=0;k<MAXZ;k++)
for(i=0;i<MAXX;i++)
for(j=0;j<MAXY;j++)
p[i][j][k]=<something>;
}
array = malloc(num_elem * num_elem * num_elem * sizeof(array_elem));
Why not? :)
#Poita_, ok, maybe you are right, but if somebody still wants to use 3-dimensional array allocated in one big chunk, here's how you add normal indexing to it:
void*** newarray(int icount, int jcount, int kcount, int type_size)
{
void*** iret = (void***)malloc(icount*sizeof(void***)+icount*jcount*sizeof(void**)+icount*jcount*kcount*type_size);
void** jret = (void**)(iret+icount);
char* kret = (char*)(jret+icount*jcount);
for(int i=0;i<icount;i++)
iret[i] = &jret[i*jcount];
for(int i=0;i<icount;i++)
for(int j=0;j<jcount;i++)
jret[i*jcount+j] = &kret[i*jcount*kcount*type_size+j*kcount*type_size];
return iret;
}
For a given type T (non-contiguous):
size_t dim0, dim1, dim2;
...
T ***arr = malloc(sizeof *arr * dim0); //type of *arr is T **
if (arr)
{
size_t i;
for (i = 0; i < dim0; i++)
{
arr[i] = malloc(sizeof *arr[i] * dim1); // type of *arr[i] is T *
if (arr[i])
{
size_t j;
for (j = 0; j < dim1; j++)
{
arr[i][j] = malloc(sizeof *arr[i][j] * dim2);
}
}
}
}
Unless you are working with a very old (pre-C89) implementation, you do not need to cast the result of malloc(), and the practice is discouraged. If you forget to include stdlib.h or otherwise don't have a prototype for malloc() in scope, the compiler will type it to return int, and you'll get an "incompatible type for assignment"-type warning. If you cast the result, the warning is suppressed, and there's no guarantee that a conversion from a pointer to an int to a pointer again will be meaningful.

allocate matrix in C

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.

Resources