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
Related
If i have a 2D array allocated as follows:
int** map;
map = malloc(number * sizeof(int*));
if(!(map)){
printf("out of memory!\n");
return 1;
}
for (int i = 0; i < number; i++){
map[i] = malloc(number * sizeof(int));
if (!(map[i])){
printf("Not enough memory!\n");
return 1;
}
}
If the allocation fails and we enter in the if statement should i free map and the "columns" allocated until now? If so, how should i do it?
Right now i just print the message and return 1 but i'm not sure if this is the correct approach.
Yes, you should free() otherwise you leak memory which might matter if this is in a long-running program.
One way to make it easier is to compute the total size of all the allocations, and do a single larger malloc() rather than a whole bunch of smaller ones. This is also (potentially much) faster, since heap allocations can be expensive.
That way, you only need to check once if it succeeded or failed, and there's nothing to free() in case of failure.
Something like this:
int ** map_allocate(size_t number)
{
int **base = malloc(number * sizeof (int *) + number * number * sizeof (int));
if(base != NULL)
{
int *row = (int *) (base + number);
for(size_t i = 0; i < number; ++i)
base[i] = row + i * number;
}
return base;
}
I didn't test-run this, but something along those lines.
You can use:
if (!(map[i])){
printf("Not enough memory!\n");
while (--i>=0)
free(map[i]);
free(map);
return 1;
}
Always set pointers to null immediately you allocate them.
int **map;
map = malloc(number * sizeof(int *));
if(!map)
goto out_of_memory;
for(i=0;i<number;i++)
map[i] = 0;
for(i=0;i<numbers;i++)
{
map[i] = malloc(number * sizeof(int));
if(!map[i])
goto out_of_memory;
}
...
return 0;
out_of_memory:
if(map)
for(i=0;i<number;i++)
free(map[i]);
free(map);
return -1;
I want to use pointer to pointer to store a dynamic array data set but I don't know how to link them together. Does anyone know how to solve this problem?
How can I initialize the pointer to pointer array using dynamic array ? And how can I pick specific data set to do further program using pointer to pointer?
float *data;
float **dataIndex;
*dataIndex = (float**)malloc(number * sizeof(float*));
data = (float*) malloc(size * sizeof(float));
for(i = 0; i < size; i++){
scanf("%f", (data + i));
}
To dynamically allocate a 2D array, you will need to use a loop to initialize each pointer in the array.
float **arr;
size_t i, n;
if ((arr = malloc(n * sizeof(float *)) == NULL)
perror("malloc");
for (i = 0; i < n; ++i)
if ((arr[i] = malloc(sizeof (float))) == NULL)
perror("malloc");
Don't forget to free your memory.
while (--n >= 0)
free(arr[n]);
free(arr);
You need to be careful to free each subarray first, and then free the entire array.
That's not how allocate for pointer to pointers.
dataIndex = malloc(number * sizeof(float*));
for(i = 0; i < number; i++)
dataIndex[i] = malloc(size * sizeof(float));
Now if you want to populate data, you need to access it like a 2D array dataIndex[i][j].
for(i = 0; i < number; i++)
for(j = 0; j < size; j++)
scanf("%f", &dataIndex[i][j]);
Also remember to check errors and free memory.
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?
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.
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.